Я хочу сделать что-то вроде этого:
myYear = record.GetValueOrNull<int?>("myYear"),
Обратите внимание на обнуляемый тип в качестве универсального параметра.
Так как GetValueOrNull
функция могла вернуть ноль, моя первая попытка была такой:
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : class
{
object columnValue = reader[columnName];
if (!(columnValue is DBNull))
{
return (T)columnValue;
}
return null;
}
Но ошибка, которую я получаю сейчас:
Тип 'int?' должен быть ссылочным типом, чтобы использовать его как параметр 'T' в универсальном типе или методе
Правильно! Nullable<int>
это struct
! Поэтому я попытался изменить ограничение класса на struct
ограничение (и как побочный эффект больше не может возвращаться null
):
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
Теперь о назначении:
myYear = record.GetValueOrNull<int?>("myYear");
Выдает следующую ошибку:
Тип 'int?' должен быть необнуляемым типом значения, чтобы использовать его в качестве параметра 'T' в универсальном типе или методе
Можно ли вообще указать тип NULL в качестве универсального параметра?
IDataRecord
отDbDataRecord
..Ответы:
Измените тип возвращаемого значения на Nullable и вызовите метод с ненулевым параметром
источник
Просто используйте это так:
источник
GetValueOrDefault
чтобы уточнить, что он возвращаетсяdefault(T)
, чемnull
. В качестве альтернативы, вы можете вызвать исключение, еслиT
оно не обнуляется.Просто сделайте две вещи с исходным кодом - удалите
where
ограничение и измените последнееreturn
сreturn null
наreturn default(T)
. Таким образом, вы можете вернуть любой тип, который вы хотите.Кстати, вы можете избежать использования
is
, изменив своеif
заявление наif (columnValue != DBNull.Value)
.источник
return default
достаточно (вам не нужно(T)
, компилятор выведет его из типа возвращаемого значения подписи).Отказ от ответственности: Этот ответ работает, но предназначен только для образовательных целей. :) Решение Джеймса Джонса, вероятно, лучшее здесь, и, конечно же, то, с которым я бы пошел.
dynamic
Ключевое слово C # 4.0 делает это еще проще, хотя и менее безопасно:Теперь вам не нужно явно указывать тип в RHS:
На самом деле, вам это даже не нужно!
value
теперь будет int, или строкой, или любым другим типом, который был возвращен из БД.Единственная проблема заключается в том, что это не мешает вам использовать ненулевые типы на LHS, и в этом случае вы получите довольно неприятное исключение во время выполнения, например:
Как и весь код, который использует
dynamic
: Caveat Coder.источник
Просто нужно было сделать что-то невероятное похожее на это. Мой код:
источник
Я думаю, что вы хотите обрабатывать ссылочные типы и структурные типы. Я использую его для преобразования строк XML-элемента в более типизированный тип. Вы можете удалить нуль-альтернативу с отражением. Формат провайдер должен обрабатывать зависимый от культуры "." или разделитель ',', например, в десятичных или целых числах и двойных числах. Это может работать:
Вы можете использовать это так:
источник
Это может быть мертвая тема, но я склонен использовать следующее:
источник
Я только что столкнулся с той же самой проблемой.
... = reader["myYear"] as int?;
работает и чисто.Работает с любым типом без проблем. Если результат DBNull, он возвращает ноль, так как преобразование не выполняется.
источник
int v=reader["myYear"]??-1;
или какой-то другой по умолчанию вместо-1
. Тем не менее, это может вызвать проблемы, если значениеDBNull
...Я знаю, что это старый, но вот другое решение:
Теперь вам все равно, было ли
T
значение или ссылочный тип. Только если функция возвращает true, у вас есть разумное значение из базы данных. Использование:Этот подход очень похож на
int.TryParse("123", out MyInt);
источник
Множественные общие ограничения не могут быть объединены способом ИЛИ (менее ограничительным), только способом И (более ограничительным). Это означает, что один метод не может обрабатывать оба сценария. Общие ограничения также нельзя использовать для создания уникальной подписи для метода, поэтому вам придется использовать 2 отдельных имени метода.
Однако вы можете использовать общие ограничения, чтобы убедиться, что методы используются правильно.
В моем случае я специально хотел вернуть значение null, а не значение по умолчанию любых возможных типов значений. GetValueOrDefault = плохо. GetValueOrNull = хорошо.
Я использовал слова «Null» и «Nullable», чтобы различать ссылочные типы и типы значений. И вот пример пары методов расширения, которые я написал, которые дополняют метод FirstOrDefault в классе System.Linq.Enumerable.
источник
Более короткий путь:
вернуться
0
кint
, иnull
дляint?
источник