我尝试使用这种通用方法扩展DataRow对象:
public static T? Get<T>(this DataRow row, string field) where T : struct
{
if (row.IsNull(field))
return default(T);
else
return (T)row[field];
}
当T为int
,decimal
,double
等时,此功能正常。
但是当我尝试使用字符串时,我有这个错误:
“类型'字符串'必须是a 不可为空的值类型以便 在通用中将它用作参数'T' 类型或方法'System.Nullable'“
我该如何纠正?
我知道字符串不是结构,但如果字符串字段是DBNull,我不会返回null。
答案 0 :(得分:6)
我认为这就是你想要的:
public static T? GetValue<T>(this DataRow row, string field) where T : struct
{
if (row.IsNull(field))
return new T?();
else
return (T?)row[field];
}
public static T GetReference<T>(this DataRow row, string field) where T : class
{
if (row.IsNull(field))
return default(T);
else
return (T)row[field];
}
答案 1 :(得分:5)
string
不是struct
,而是class
。这就是错误消息告诉您的内容。只需删除约束。
也许您想查看DataRowExtensions。
答案 2 :(得分:2)
不幸的是,除非您指定在进行呼叫时返回Nullable,否则您无法通过使用泛型来获取Nullable返回类型并支持引用类型
public static T Get<T>(this DataRow row, string field)
{
if (row.IsNull(field))
return default(T);
else
return (T)row[field];
}
当你打电话
var id = dr.Get<int?>("user_id");
我没有对此进行测试,只是把它扔到了这里。试一试。
编辑:
或者,如果你真的想将值类型转换为nullables并且仍然能够支持类似这样的引用类型
public static object GetDr<T>(this DataRow row, string field)
{
// might want to throw some type checking to make
// sure row[field] is the same type as T
if (typeof(T).IsValueType)
{
Type nullableType = typeof(Nullable<>).MakeGenericType(typeof(T));
if (row.IsNull(field))
return Activator.CreateInstance(nullableType);
else
return Activator.CreateInstance(nullableType, new[] { row[field] });
}
else
{
return row[field];
}
}
但是,每次使用都需要演员
var id = dr.Get<string>("username") as string;
var id = (int?)dr.Get<int>("user_id");
然而,这并不像在通用类型参数中接受可空类型那样有效。
答案 3 :(得分:2)
ds.Tables[7].Rows.OfType<DataRow>().ToList().ForEach(f => tempList.Add(new MyEntity
{
Id = int.Parse(f.ItemArray[0].ToString()),
Title = f.ItemArray[1].ToString()
}));
答案 4 :(得分:1)
正如Wes所指出的,你的问题是结构的约束。我希望扩展方法能够在没有约束的情况下工作......
啊,我现在看到了,你正在回归T?
嗯,我不确定但你能定义方法的两个变体,一个约束到struct
,另一个约束到class
并返回T
?
答案 5 :(得分:1)
您有一个明确的条件阻止它使用字符串:
where T : struct
System.String是一个类,而不是结构。如果您的目标是处理值类型和字符串,我会为字符串创建一个单独的方法,并将其单独留给其他类型。
答案 6 :(得分:1)
这样的事情怎么样?与您的示例不完全相同,但非常适用于引用类型,可空值的类型和不可为空的值类型:
int v = row.Get<int>("vvv"); // throws if column is null
int? w = row.Get<int?>("www"); // set to null if column is null
int x = row.Get<int?>("xxx") ?? -1; // set to -1 if column is null
string y = row.Get<string>("yyy"); // set to null if column is null
string z = row.Get<string>("zzz") ?? "" // set to "" if column is null
// ...
public static T Get<T>(this DataRow source, string columnName)
{
if (source == null)
throw new ArgumentNullException("source");
if (columnName == null)
throw new ArgumentNullException("columnName");
if (columnName.Length < 1)
throw new ArgumentException("Name cannot be empty.", "columnName");
if (source.IsNull(columnName))
{
T defaultValue = default(T);
if (defaultValue == null)
return defaultValue;
}
// throws if the column is null and T is a non-nullable value type
return (T)source[columnName];
}