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

Следующий код не скомпилирует:

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

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

Для фиксации этого я должен сделать что-то вроде этого:

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

Этот бросок кажется бессмысленным, поскольку это, конечно, законно:

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

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

В моем уме первый оператор должен быть законным...

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

Спасибо.

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

РЕДАКТИРОВАНИЕ (Jon Skeet): Удаленный тег "автоупаковки" как никакая упаковка вовлечен в этот вопрос.

40
задан Mechanical snail 14 August 2012 в 00:59
поделиться

3 ответа

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

РЕДАКТИРОВАНИЕ: Похож на него, действительно законно в Java. Вполне, как это разрабатывает, что сделать когда дело доходит до перегрузки метода, я не уверен... Я только что посмотрел на JLS, и чрезвычайно неясно о том, что - тип условного выражения, когда существует два несовместимых включенные ссылочных типа. Способ C# работать может иногда быть более раздражающим, но это - более ясный IMO.

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

вторые и третьи операнды?: управление оператором тип условного выражения. Позвольте X и Y быть типами вторых и третьих операндов. Затем

  • , Если X и Y являются тем же типом, то это - тип условного выражения
  • Иначе, если неявное преобразование (В§6.1) существует от X до Y, но не от Y до X, то Y является типом условного выражения.
  • Иначе, если неявное преобразование (В§6.1) существует от Y до X, но не от X до Y, то X тип условного выражения.
  • Иначе, никакой тип выражения не может быть определен, и ошибка времени компиляции происходит.
69
ответ дан Jon Skeet 27 November 2019 в 01:20
поделиться

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 и выше Вас может явно поддерживать динамические типы, но я не думаю, что это помогает здесь.

18
ответ дан Keith 27 November 2019 в 01:20
поделиться

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

object result = (object)foo ?? DBNull.Value;
10
ответ дан Konrad Rudolph 27 November 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: