C#?: Условный оператор

  1. Статья Википедии. Мне инверсия управления поворачивает Ваш последовательно записанный код и превращает его в структуру делегации. Вместо Вашей программы, явно управляющей всем, Ваша программа настраивает класс или библиотеку с определенными функциями, которые назовут, когда определенные вещи происходят.

  2. Это решает дублирование кода. Например, в былые времена Вы вручную записали бы свой собственный цикл событий, опросив системные библиотеки относительно новых событий. В наше время, самые современные API, которые Вы просто говорите системным библиотекам, какие события Вы интересуетесь, и это сообщит, когда они произойдут.

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

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

41
задан johnnyRose 20 October 2017 в 19:34
поделиться

7 ответов

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога 27 мая 2010 года . Спасибо за отличный вопрос!

Здесь очень много очень запутанных ответов. Попробую точно ответить на ваш вопрос. Давайте упростим это:

object value = whatever;
bool condition = something;
decimal result = (decimal)(condition ? value : 0);

Как компилятор интерпретирует последнюю строку? Проблема, с которой сталкивается компилятор, заключается в том, что тип условного выражения должен быть согласован для обеих ветвей ; правила языка не позволяют вам возвращать объект в одной ветке и int - в другой. Возможные варианты: объект и int. Каждый int может быть преобразован в объект, но не каждый объект может быть преобразован в int, поэтому компилятор выбирает объект. Следовательно, это то же самое, что и

decimal result = (decimal)(condition ? (object)value : (object)0);

Следовательно, возвращаемый ноль - это заключенное в рамку целое число.

Затем вы распаковываете int в десятичное. Недопустимо распаковывать упакованные int в десятичные числа. Чтобы узнать, почему, см. Статью в моем блоге по этой теме:

Представление и идентичность

По сути, ваша проблема в том, что вы действуете так, как если бы преобразование в десятичное было распределено, например:

decimal result = condition ? (decimal)value : (decimal)0;

Но поскольку мы Я видел, что

decimal result = (decimal)(condition ? value : 0);

означает не это. Это означает «превратить обе альтернативы в объекты, а затем распаковать получившийся объект».

101
ответ дан 27 November 2019 в 00:12
поделиться

Разница в том, что компилятор не может определить тип данных, который хорошо соответствует между Object и Int32 .

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

result = (decimal)(valueFromDatabase != DBNull.value ? valueFromDatabase : (object)0);

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

result = (decimal)(valueFromDatabase != DBNull.value ? valueFromDatabase : (object)0M);
12
ответ дан 27 November 2019 в 00:12
поделиться

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

Вот отрывок из спецификации C #:

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

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

Ваша строка должна быть такой:

result = valueFromDatabase != DBNull.value ? (decimal)valueFromDatabase : 0m;

0m - десятичная константа для нуля

Обе части условного оператора должны оценивать один и тот же тип данных

4
ответ дан 27 November 2019 в 00:12
поделиться

Часть x: y требует общего типа, значение базы данных, вероятно, представляет собой какое-то число с плавающей точкой, а 0 - это внутр. Это происходит до преобразования в десятичное. Попробуйте ": 0.0" или ": 0D".

3
ответ дан 27 November 2019 в 00:12
поделиться

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

См. MSDN для получения дополнительной информации.

2
ответ дан 27 November 2019 в 00:12
поделиться

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

0
ответ дан 27 November 2019 в 00:12
поделиться
Другие вопросы по тегам:

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