Почему этот код недействителен в C #?

Следующий код не будет компилироваться:

string foo = "bar"; Object o = foo == null ? DBNull.Value : foo; 

Я получаю: Ошибка 1 Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между ‘System.DBNull’ и ‘string’

Чтобы исправить это, я должен сделать что-то вроде этого:

 string foo = "bar"; Object o = foo == null ? DBNull.Value : (Object)foo; 

Это действие кажется бессмысленным, поскольку это, безусловно, является законным:

 string foo = "bar"; Object o = foo == null ? "gork" : foo; 

Мне кажется, что, когда тройные ветви имеют разные типы, компилятор не будет автоматически определять значения для объекта типа … но когда они имеют один и тот же тип, автооблок автоматически.

На мой взгляд, первое заявление должно быть законным …

Может ли кто-нибудь описать, почему компилятор не позволяет этого и почему разработчики C # решили сделать это? Я считаю, что это законно на Java … Хотя я этого не подтвердил.

Благодарю.

EDIT: Я прошу понять, почему Java и C # обрабатывают это по-другому, что происходит под сценами на C #, которые делают это недействительным. Я знаю, как использовать тернар, и я не ищу «лучший способ» для кода примеров. Я понимаю правила тройного в C #, но я хочу знать, ПОЧЕМУ …

EDIT (Jon Skeet): Удален тег «autoboxing», так как в этом вопросе не участвует ни один бокс.

Компилятор требует, чтобы либо типы второго, и третьего операндов были одинаковыми, или что они неявно конвертируются в другую. В вашем случае типы DBNull и строка, ни одна из которых неявно конвертируется в другую. Кастинг любого из них на объект решает это.

EDIT: Похоже, это действительно законно на Java. Довольно, как это работает, что делать, когда дело доходит до перегрузки метода, я не уверен … Я только что посмотрел на JLS, и очень неясно, какой тип условного является, когда есть две несовместимые ссылки типы. C # способ работы может быть более раздражающим иногда, но это яснее ИМО.

Соответствующий раздел спецификации C # 3.0 равен 7.13, условный оператор:

Второй и третий операнды оператора?: Управляют типом условного выражения. Пусть X и Y – типы второго и третьего операндов. Затем,

  • Если X и Y являются одним и тем же типом, то это тип условного
  • В противном случае, если неявное преобразование (§6.1) существует от X до Y, но не от Y до X, то Y является типом условного выражения.
  • В противном случае, если неявное преобразование (§6.1) существует от Y до X, но не от X до Y, то X является типом условного выражения.
  • В противном случае тип выражения не может быть определен, и возникает ошибка времени компиляции.

DBNull.Value возвращает тип DBNull .

Вы хотите, чтобы тип был string .

Хотя string может быть null она не может быть DBNull .

В вашем коде оператор справа от равных выполняется перед назначением объекту.

В основном, если вы используете:

 [condition] ? true value : false value; 

В .Net оба истинных и ложных варианта должны быть неявно конвертируемыми в один и тот же тип, прежде чем вы их назначили.

Это результат того, как C # имеет дело с безопасностью типа. Например, допустимо следующее:

 string item = "item"; var test = item != null ? item : "BLANK"; 

C # 3 не поддерживает динамические типы, поэтому что такое тест? В C # каждое присваивание также является выражением с возвращаемым значением, поэтому, хотя конструкция var является новой в C # 3, оператор справа от равных всегда должен разрешаться для одного типа.

В C # 4 и выше вы можете явно поддерживать динамические типы, но я не думаю, что это помогает.

Кстати, ваш код – это особый случай, который вообще не должен использовать условный оператор. Вместо этого оператор нулевой коалесценции является более подходящим (но все равно требует кастинга):

 object result = (object)foo ?? DBNull.Value; 
  • Как назначить Func условно между lambdaми, используя условный тернарный оператор?
  • Почему оператор условного оператора является ассоциативным?
  • Почему std :: istringstream выглядит по-разному в std :: ifstream в тройном (? :) операторе?
  • Как использовать условный оператор?
  • Преимущества использования условного?: (Тройного) оператора
  • В C # почему оператор условного оператора неявно не вводится в тип с нулевым значением
  • Давайте будем гением компьютера.