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

Почему T.TryParse не возвращает Nullable <T>

Насколько я знаю, int.TryParse(string, out int) существует с Framework 2.0. Таким образом, int?.

Есть ли причина использовать параметр out вместо того, чтобы возвращать int? с HasValue, установленным в true of false, в зависимости от способности конвертировать?

4b9b3361

Ответ 1

Я не могу рассказать о реальных причинах, но я вижу три возможные причины:

1) Nullable types были введены в .NET 2.0, а первые TryParse методы были уже с .NET 1.1. Таким образом, когда вводились типы с нулевым значением, было слишком поздно для такого изменения API; и новые классы не будут реализовывать TryParse иначе, потому что шаблон уже установлен.

2) Не все типы могут использоваться с структурой Nullable, могут использоваться только типы значений. Однако существуют методы, следующие за шаблоном Try*, которые должны возвращать ссылочные типы. Например, словарь может полностью законно содержать null как элемент, поэтому его метод TryGetValue требует дополнительного способа выразить, что ключ не найден.

3) Способ записи Try* -методов, можно написать такой код:

int myValue;
if (int.TryParse("42", out myValue)) {
    // do something with myValue
}
    // do something else
}

Теперь, представьте, если TryParse вернул int?. Вы можете либо избавиться от переменной myValue и потерять результат:

if (int.TryParse("42").HasValue) {
    // do something with ... what? You didn't store the conversion result!
}
    // do something else
}

Или вы можете добавить переменную с нулевым значением:

int? myValue = int.TryParse("42");
if (myValue.HasValue) {
    // do something with myValue.Value
}
    // do something else
}

Это больше не является преимуществом по сравнению с текущей версией, а вместо этого требует записи myValue.Value в некоторых более поздних экземплярах, где в противном случае достаточно простого value. Обратите внимание, что во многих случаях вам нужна только информация о том, была ли операция успешной для оператора if.

Ответ 2

Простая причина в том, что, когда int.TryParse был добавлен к языку, Nullable<T> не существовало.

В это сообщение в блоге Эрика Липперта, есть строка внизу, которая гласит:

Решение состоит в том, чтобы написать собственную версию метода TryParse для расширения, как это было бы написано, если бы были доступны типы с нулевыми значениями

который дает понять, что типы с нулевым значением недоступны для использования в исходной реализации TryParse. Эрик Липперт был в команде, которая написала компилятор С#, поэтому я бы сказал, что это довольно авторитетный источник.

Ответ 3

Вот цитата из блога Джулии Лерман (Back from 2004):

Я играл с nullable в битках предварительного просмотра в марте, но еще не в мае, и разочаровался в текущем (но ожидаемом серьезном улучшении командой bcl team!!!), когда сравнивал использование nullable<t> над текущими вариантами. Так, например, со значениями типов:

сравнение myNullableInt.HasValue to (в VB) myInt < 0

или с ссылочными типами

сравнивая myNullableThing.HasValue с "if not myThing=null"

тип с нулевым значением в настоящее время намного медленнее. Я был , обещанный несколькими членами команды BCL, что план должен сделать значение NULL MUCH более эффективным.

Мне также был дан намек на то, что в будущем возможно следующее:

Nullable<T> Parse(string value); 
Nullable<Int32> i = Int32.Parse( some String );

И будет более результативным, чем TryParse. Так что это тоже будет интересно.

Я предполагаю, что, как всегда, преимущество перевешивает стоимость.

В любом случае, в предстоящем С# vNext вы можете сделать:

DateTime.TryParse(s, out var parsedDateTime);

Поворот TryParse в один лайнер.

Ответ 4

Еще одна возможная причина:

Generics для .NET и С# в их текущей форме почти не произошло: это был очень близкий вызов, и функция почти не делала разрезание для Whidbey (Visual Studio 2005). Такие функции, как запуск CLR-кода в базе данных, получили более высокий приоритет.

...

В конечном счете, модель стирания дженериков была бы принята, как и для Java, так как команда CLR никогда не использовала бы разработку дженериков в VM без внешней помощи.

источник: http://blogs.msdn.com/b/dsyme/archive/2011/03/15/net-c-generics-history-some-photos-from-feb-1999.aspx

Моя точка зрения: большинство изменений в BCL (или, по крайней мере, те, которые напрямую не связаны с дженериками), вероятно, необходимы для работы как с дженериками, так и без них, в случае, если в окончательной RTM была отключена функция.

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

Ответ 5

Что касается причин, мы можем только догадываться, но возможны некоторые причины:

Накладные расходы на присвоение: значение в коробке несет некоторые (небольшие) служебные данные по производительности по встроенному типу.

Нет реальных выигрышей:

int res;
if int.TryParse("one", out res) {
  //something
}

не намного хуже, чем

int? res = int.TryParse("one");
if (res.HasValue){
  int realres = res.Value
  //something
}