【发布时间】:2015-10-18 06:52:00
【问题描述】:
这纯粹是好奇/挑战,根本没有实际意义。 所以我不是在寻找完成工作的替代解决方案。
从这个问题Most efficient way to check for DBNull and then assign to a variable? 我发现this answer 看起来像:
oSomeObject.IntMemeber = oRow["Value"] as int? ?? iDefault;
oSomeObject.StringMember = oRow["Name"] as string ?? sDefault;
我可以将上述表达式移动到一个通用函数(或两个,或更多),以便它同时接受int? 和string,我可以这样称呼它:
oSomeObject.IntMemeber = oRow.Read<int?>("Value", 0); //iDefault is now 0
//or
oSomeObject.IntMemeber = oRow.Read<int>("Value"); //iDefault is now default(int)
//and
oSomeObject.StringMember = oRow.Read<string>("Name"); //sDefault is now default(string)
要求:
1) 在DBNulls 的情况下,我需要一个选项来指定默认值。如果我没有指定默认值,我还需要一个返回default(T) 的选项。所以这行不通:
public static T Read<T>(this IDataRecord dr, string field, T defaultValue) where T : class
{
return dr[field] as T ?? defaultValue;
}
public static T? Read<T>(this IDataRecord dr, string field, T? defaultValue) where T : struct
{
return dr[field] as T? ?? defaultValue;
}
因为我不能打电话给oSomeObject.StringMemeber = oRow.Read<string>("Name")
它不需要是可选参数,它甚至可以是一个重载:
public static T Read<T>(this IDataRecord dr, string field) where T : class
{
return dr[field] as T ?? default(T);
}
public static T? Read<T>(this IDataRecord dr, string field) where T : struct
{
return dr[field] as T? ?? default(T?);
}
public static T Read<T>(this IDataRecord dr, string field, T defaultValue) where T : class
{
return dr[field] as T ?? defaultValue;
}
public static T? Read<T>(this IDataRecord dr, string field, T? defaultValue) where T : struct
{
return dr[field] as T? ?? defaultValue;
}
这不会编译,因为方法 1 和 2 具有相同的签名。
2) 泛型函数(在重载的情况下)应该具有相同的名称。
3) as 关键字必须使用检查和强制转换类型。正如我之前所说,我并不是真的在寻找从IDataRecord 读取或提高性能或其他东西的解决方案。
有类似的问题
C# generic class using reference types and nullable value types
Is creating a C# generic method that accepts (nullable) value type and reference type possible?
Can a Generic Method handle both Reference and Nullable Value types?
但这对于as 关键字非常具体。所以那里的答案不适用。
附录:我知道不会有一个单一的解决方案。我会接受哪个是最优雅的选择。
【问题讨论】:
-
“通用”意味着相同的 IL 可用于匹配约束的 所有 类型。问题是引用类型和可为空的值类型对于同一个运算符需要不同的 IL (
as)。所以你需要不同的方法。并且同名方法的参数列表必须不同。因此,除非您正在寻找一种解决方案,例如在运行时为每种类型编译一些 IL,否则我会说它不会比您已经拥有的更优雅。 -
嗯,但遗憾的是我还没有解决方案。
-
为您的方法使用不同的名称?
-
是的,这总是可能的。似乎这是最优雅的解决方案:)
标签: c# generics nullable overload-resolution as-keyword