Подтвердить что ты не робот

Почему Convert.ToInt32 (null) возвращает 0 в С#

Я только что наткнулся на это сегодня, если вы конвертируете null в int32

Convert.ToInt32(null)

он возвращает 0

Я ожидал InvalidCastException...

Любая идея, почему это происходит?

4b9b3361

Ответ 1

Любая идея, почему это происходит?

Потому что это документированное поведение? Будь то Convert.ToInt32(object) или Convert.ToInt32(string), документация гласит достаточно четко:

(Под возвратным значением)

32-разрядное целое число со знаком, эквивалентное числу в значении, или 0 (ноль), если значение равно null.

или

32-разрядное целое число со знаком, эквивалентное значению, или ноль, если значение равно null.

Как всегда, если реальность не соответствует ожиданиям, первое, что вам нужно сделать, это проверить, соответствуют ли ваши ожидания документированному поведению.

Лично я не полностью покупаю аргумент "совместимость с VB6", показанный Gavin. Я понимаю, что это происходит от Microsoft, и вполне может быть подлинной причиной, почему она ведет себя именно так, но я не думаю, что это хорошая причина для этого. Существует множество специфических для VB методов конверсии, поэтому, если дизайнеры фреймворков искренне думали, что возврат нуля был неидеальным результатом, они должны были сделать все, что они считали лучшими, и обеспечили совместимость с VB6 для использования программистами VB6.

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

Ответ 2

См. Http://msdn.microsoft.com/en-us/library/sf1aw27b.aspx

редактировать

URL-адрес выше автоматически возвращается к последней версии Framework, где текст ниже был специально размещен на версии 4. См. Пересмотренный URL-адрес ниже, который показывает текст.

http://msdn.microsoft.com/en-us/library/sf1aw27b(v=vs.100).aspx

Это объясняет:

Все методы преобразования строк в число в классе Convert возвращают ноль, если строка равна null. Первоначальной мотивацией для этого поведения было то, что они предоставили набор методов преобразования для программистов, мигрирующих с Visual Basic 6 в Visual Basic.NET, которые отражают поведение существующих методов преобразования Visual Basic 6. Предполагалось, что программистам на С# было бы более комфортно работать с операторами литья, тогда как в Visual Basic традиционно использовались методы преобразования для преобразования типов.

Традиционно.NET Framework пыталась поддерживать высокую степень совместимости от версии к версии. Эффективно это означает, что, если не было чрезвычайно убедительной причины, когда метод был реализован определенным образом и что реализация публично раскрыта (как в методе, возвращающем 0, если строковый параметр равен нулю), его нельзя изменить, поскольку это будет нарушать код, который зависит от установленного поведения. Это делает обе предлагаемые вами решения очень проблематичными. В первом случае бросание исключения изменяет реализацию метода для клиентов, которые могут зависеть от метода, возвращающего нуль для нулевой строки. Во втором случае важно помнить, что.NET Framework не рассматривает тип возврата при разрешении перегрузки. Это означает, что ваш метод должен будет заменить существующий метод Convert.ToInt32 (String value) и что весь код, который не ожидает обработки типа с нулевым значением, теперь будет нарушен.

Эта проблема совместимости еще сильнее в случае методов преобразования строк в число в классе Convert, поскольку Parse является рекомендуемым методом для преобразования строк в числовые для каждого из примитивных числовых типов, поддерживаемых.NET. Framework, и каждый метод Parse ведет себя иначе, чем соответствующий метод Convert. В отличие от метода преобразования строк в число в классе Convert, который возвращает ноль, если строка, которая должна быть преобразована, равна null, каждый метод Parse генерирует ArgumentNullException, о чем вы говорите. Перегрузки числовых методов Parse, таких как Int32.Parse и Double.Parse, также имеют то преимущество, что позволяют значительно более мелкомасштабный контроль над операцией синтаксического анализа.

Ответ 3

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

Ответ 4

Потому что что задокументировано, что он вернется. Возможно, вы думали о (int)null, который был бы NullReferenceException (не InvalidCastException; я не уверен, почему).

Ответ 5

Так как метод написан в классе Convert. Если значение параметра null, оно просто возвращает 0.

public static int ToInt32(object value)
{
    if (value == null)
    {
        return 0;
    }
    else
    {
        return ((IConvertible)value).ToInt32(null);
    }
}

Ответ 6

Чтобы иметь InvalidCastException, вам нужно сделать неконтролируемый.

Например:

int i = (int)null;

Если вы выполните его, следует добавить исключение.

Использование

Convert.ToInt32(var)

Полезно, если вы недоверяете значения в var, как при чтении из базы данных.