Проблема заключается в слове «null». Что это значит? null
может означать, что значение неопределимо, исключение было выбрано просто, что значение равно null или другому контекстуальному значению. Ваш вопрос - прекрасный пример, потому что вы, сами, произвольно заявляете, что, по вашему мнению, null
означает, что разбор строки не прошел.
Парадигма TryParse от Microsoft отличная, но для ограниченного использования. Рассмотрим эти сценарии:
- строка == "89"
- строка == NULL
- строка == "Hello World"
- строка == ""
- строка == "2147483650"
Однако, ваши единственные варианты - назначить Integer или Null на ваш вывод и вернуть true или false.
Предполагая, что это сработало, что вы собираетесь делать с этой информацией?Что-то вроде этого?
int? value = null;
if (int.TryParse(Session["Key"].ToString(), out value)) {
if (value == null)
// Handle "Appropriate" null
else
// Handle appropriate numeric value
}
else {
// Note: value == null here, and TryParse failed
// Handle null...
// What if the reason it failed was because the number was too big?
// What if the string was Empty and you wanted to do something special?
// What if the string was actually junk? Like "(423)322-9876" ?
// Long-Story Short: You don't know what to do here without more info.
}
Рассмотрим пример NullableInt TryParse:
public bool TryParseNullableInt(string input, out int? output)
{
int tempOutput;
output = null;
if (input == null) return true;
if (input == string.Empty) return true; // Would you rather this be 0?
if (!int.TryParse(input, out tempOutput))
return false; // What if string was "2147483650"... or "Twenty Three"?
output = tempOutput;
return true;
}
Одним из решений является использование перечисления TryParse вместо булевой TryParse:
public ParseStatus TryParseNullableInt(string input, out int? output)
{
int tempInteger;
output = null;
if (input == null) return ParseStatus.Success;
if (input == string.Empty) { output = 0; return ParseStatus.Derived; }
if (!int.TryParse(input, out tempInteger)) {
if (ParseWords(input, out tempInteger)) { // "Twenty Three" = 23
output = tempInteger;
return ParseStatus.Derived;
}
long tempLong;
if (long.TryParse(input, out tempLong))
return ParseStatus.OutOfRange;
return ParseStatus.NotParsable;
}
output = tempInteger;
return ParseStatus.Success;
}
Другой проблемой является существование переменной out
, Ваш третий вариант заключается в использовании описательной монады, что-то вроде этого:
public Maybe<int?> TryParseNullableInt(string input)
{
if (input == null) return Maybe.Success(null);
if (input == string.Empty) { return Maybe.Derived(0); }
int tempInteger;
if (!int.TryParse(input, out tempInteger)) {
if (ParseWords(input, out tempInteger)) { // "Twenty Three" = 23
return Maybe.Derived(tempInteger);
}
long tempLong;
if (long.TryParse(input, out tempLong))
return Maybe.OutOfRange();
return Maybe.NotParsable();
}
return Maybe.Success(tempInteger);
}
Вы можете использовать монады как Single-перечислимые значения, или как так:
Maybe<int?> result = TryParseNullableInt("Hello");
if (result.HasValue) {
if (result.Status == ParseStatus.Success)
// Do something you want...
else if (result.Status == ParseStatus.Derived)
// Do something else... more carefully maybe?
}
else if (result.Status == ParseStatus.OutOfRange)
MessageUser("That number is too big or too small");
else if (result.Status == ParseStatus.NotParsable)
// Do something
С Монадой, и, возможно, счетными TryParses, теперь у вас есть вся необходимая информация из описательного возврата, и никто не должен угадать, что может означать null
.
Почему бы не выполнять регулярные работы? '(int?) (Session [" Key "])' –
@AlexeiLevenkov Я мог бы потенциально сделать: 'Session [" Key "] как int?', где он возвращает значение NULL, если он терпит неудачу. – Greg
Я немного смущен - я полагаю, вы поместили nullable в состояние сеанса - так что будет либо допустимое значение «int?», Либо отсутствие ключа - оба должны работать с cast/as успешно. Я не вижу случая, когда «он терпит неудачу» ... –