我想做这样的事情:
myYear = record.GetValueOrNull<int?>("myYear"),
请注意可空类型作为通用参数 .
由于 GetValueOrNull
函数可以返回null,我的第一次尝试是这样的:
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”
是否可以将可空类型指定为通用参数?
10 回答
将返回类型更改为Nullable,并使用非可空参数调用该方法
只需使用它:
只需对原始代码执行两项操作 - 删除
where
约束,并将最后一个return
从return null
更改为return default(T)
. 这样你就可以返回你想要的任何类型 .顺便说一句,您可以通过将
if
语句更改为if (columnValue != DBNull.Value)
来避免使用is
.只需做一些与此类似的令人难以置信的事情 . 我的代码:
Disclaimer: 此答案有效,但仅用于教育目的 . :)詹姆斯琼斯' solution is probably the best here and certainly the one I'去吧 .
如果不太安全,C#4.0的
dynamic
关键字会让这更容易:现在,您不需要在RHS上显式类型提示:
事实上,你根本不需要它!
value
现在将是一个int,或一个字符串,或从DB返回的任何类型 .唯一的问题是,这并不妨碍您在LHS上使用不可为空的类型,在这种情况下,您将获得一个相当讨厌的运行时异常,如:
与使用
dynamic
的所有代码一样:告诫编码器 .我想你想要处理引用类型和结构类型 . 我用它将XML Element字符串转换为更类型的字符串 . 您可以使用反射删除nullAlternative . formatprovider用于处理依赖于文化的' . '或','分隔符,例如小数或整数和双精度数 . 这可能有效:
你可以像这样使用它:
这可能是一个死线程,但我倾向于使用以下内容:
我自己也遇到了同样的问题 .
... = reader["myYear"] as int?;
工作,很干净 .它适用于任何类型,没有问题 . 如果结果是DBNull,则在转换失败时返回null .
我知道这是旧的,但这是另一种解决方案:
现在,您不关心
T
是值还是引用类型 . 仅当函数返回true时,您才能从数据库中获得合理的值 . 用法:这种方法与
int.TryParse("123", out MyInt);
非常相似多个通用约束不能以OR方式组合(限制性较小),仅以AND方式(更具限制性)组合 . 意味着一种方法无法处理这两种情况 . 通用约束也不能用于为方法创建唯一的签名,因此您必须使用2个单独的方法名称 .
但是,您可以使用通用约束来确保正确使用方法 .
在我的例子中,我特别希望返回null,而不是任何可能的值类型的默认值 . GetValueOrDefault =坏 . GetValueOrNull =好 .
我使用“Null”和“Nullable”这两个词来区分引用类型和值类型 . 这里是我编写的一些扩展方法的示例,它们补充了System.Linq.Enumerable类中的FirstOrDefault方法 .