Как компилятор C# гарантирует успех преобразования?

Я изучаю C# 7.0 в двух словах, 7-е издание. Есть часть текста, которую я не мог понять (страницы 24 и 25)

"Implicit conversions are allowed when both of the following are true:

1) The compiler can guarantee they will always succeed.

2) No information is lost in conversion. (A minor caveat is that very large long values lose some precision when converted to double)

Conversely, explicit conversions are required when one of the following is true:

1)The compiler cannot guarantee they will always succeed.

2)Information may be lost during conversion."

If the compiler can determine that a >conversion will always fail, both kinds of conversion are prohibited"

Вы можете привести примеры, когда компилятор не может гарантировать преобразование?

double в int?
stuartd 18.12.2018 12:49

см. softwareengineering.stackexchange.com/questions/284359/…

HimBromBeere 18.12.2018 12:55

лучший способ научиться этому - создать консольное приложение и поиграть, много веселья там

MrVoid 18.12.2018 12:57

Например, приведение ссылки интерфейса IFoo к объекту Foo. Компилятор не может быть уверен, что это действительно может быть объект класса Bar, который также реализует IFoo. Если это так, вы получите исключение InvalidCastException во время выполнения. В общем, любое преобразование, которое является восходящим, переходя от менее специализированного типа к более специализированному типу. В целом плохая идея, но иногда неизбежная. Примеры с плавающей запятой не очень хороши, они действительно успешны во время выполнения, и вы получите число, которое может вас удивить.

Hans Passant 18.12.2018 13:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
4
105
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Неявные преобразования существуют для преобразования типа данных, например short в int или int в long. Другой пример - это int в float или double. Такие типы данных всегда можно привести к их более крупным аналогам.

Обратное неверно: double (всегда) не может быть преобразован в int. long не всегда подходит к int или short.

для добавления контекста примером явного преобразования будет строка в целое число, потому что вы никогда не узнаете, является ли содержимое строки числом, буквенно-цифровым или просто текстовым значением

MrVoid 18.12.2018 12:54
double - int также имеет явный оператор. @MrVoid
Patrick Hofman 18.12.2018 12:55

да, вы на 100% правы, я просто подумал, что просто числовые значения могут иногда немного сбивать с толку.

MrVoid 18.12.2018 12:56

Спасибо за ваш ответ. Так компилятор определяет, гарантировать ли преобразование только размер данных?

Coder 18.12.2018 12:57

Нет. Как сказал MrVoid, это зависит от обоих типов данных. Например, все с string - плохой выбор. @Coder

Patrick Hofman 18.12.2018 12:59

Извините только что прочитал его комментарий. Да, это интересный пример. Где я могу узнать об этом подробнее? Я пытаюсь думать, как компилятор, чтобы учесть возможные случаи.

Coder 18.12.2018 13:01

"Что-нибудь со строкой - плохой выбор, например.", Можете ли вы пояснить @PatrickHofman? Благодарность

MrVoid 18.12.2018 13:03

@MrVoid Ну, было бы сложно неявно преобразовать любой тип данных из и в строку.

Patrick Hofman 18.12.2018 13:04

да, видно, это не очень хороший пример для всей картины.

MrVoid 18.12.2018 13:07
double в int и long в int или short не являются примерами случая 1, а случая 2. Они могут потерять информацию, но никогда не выходят из строя. Примером преобразования, которое может привести к сбою, может быть преобразование объекта класса в подкласс.
sepp2k 18.12.2018 13:09

@ sepp2k Мой первый абзац наоборот, и там можно без потерь конвертировать.

Patrick Hofman 18.12.2018 13:12

Потому что именно так работает Stack Overflow @Coder. Просто выберите тот, который вам больше всего помог.

Patrick Hofman 18.12.2018 13:14

@PatrickHofman Конечно, я говорил о втором абзаце. В книге перечислены две причины, по которым преобразование не может быть неявным: 1) оно может потерпеть неудачу или 2) оно может привести к потере информации. OP попросил привести примеры, в которых преобразование может завершиться неудачно (например, случай 1). Я говорю, что вы привели примеры случая 2 во втором абзаце, но вы не привели никаких примеров случая 1.

sepp2k 18.12.2018 13:15

Или, другими словами: doubleможет всегда конвертируется в int (нет ситуации, когда (int)myDouble когда-либо вызовет исключение - в отличие, скажем, от (MySubclass)myObject), он просто не всегда может быть преобразован без потери информации.

sepp2k 18.12.2018 13:17
Ответ принят как подходящий

Примером того, когда компилятор не может гарантировать преобразование, может быть предположение о типах во время выполнения. Очень простой пример может быть это

public int Add(object a, object b)
{
    return ((int)a) + ((int)b);
}

Здесь вы работаете с предположением, что вам будет передано int во время выполнения, по какой-либо причине вы потеряли безопасность типа и работаете с объектом. Компилятор не знает и не может знать этого во время компиляции, поэтому вам нужно явное приведение.

Это крайний пример, но, надеюсь, он немного проясняет его.

Пока что ответы сосредоточены на типах значений.

Для ссылочных типов существуют преобразования базового класса, производного класса и интерфейса.

class A  { }       // base class
class B : A { }    // B is-an A 
class C : A { }    // C is-an A 

B b = new B(); // instance of B 
A a = b;       // ok, conversion to base class can't fail because B is an A
C c = (C) a;   // but conversion to derived could fail, a could be a B 

Другие вопросы по теме