DataRow 的通用字段 getter

发布于 2024-10-17 01:47:43 字数 527 浏览 3 评论 0原文

我尝试使用此通用方法扩展 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 为 intdecimaldouble 等时,它工作正常。

但是当我尝试与字符串一起使用,我有这个错误:

“‘字符串’类型必须是 不可为 null 的值类型,以便 将其用作泛型中的参数“T” 类型或方法“System.Nullable””

如何更正此问题?

我知道字符串不是结构,但如果字符串字段为 DBNull,我不想返回 null。

I try to extend the DataRow object with this generic method :

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];
}

It's work fine when T is int, decimal, double, etc.

But when I try to use with string, I have this error :

"The type 'string' must be a
non-nullable value type in order to
use it as parameter 'T' in the generic
type or method 'System.Nullable'"

How can I correct this ?

I know that string is not a struct but I wan't to return null if the string field is DBNull.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

a√萤火虫的光℡ 2024-10-24 01:47:43

我认为这就是你想要的:

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];
}

I think that this is what you want:

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];
}
等往事风中吹 2024-10-24 01:47:43

string 不是一个struct,而是一个class。这就是错误消息告诉您的内容。只需删除约束即可。

也许您想查看DataRowExtensions

string is not a struct, but a class. That is what the error message tells you. Just remove the constraint.

Maybe you want to have a look at the DataRowExtensions.

回梦 2024-10-24 01:47:43

You have an explicit condition that prevents this from working with string:

 where T : struct

System.String is a class, not a struct. If your goal is to handle value types and string, I would make a separate method for string, and leave this alone for your other types.

白鸥掠海 2024-10-24 01:47:43
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()
 }));
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()
 }));
半岛未凉 2024-10-24 01:47:43

不幸的是,您将无法通过使用泛型获得 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");

我没有对此进行测试,只是把它扔在这里。试一试。

编辑:

或者,如果您确实想将值类型转换为可空值并且仍然能够支持引用类型,类似这样的东西可能会起作用

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");

,但是,这不会像这样与仅接受泛型类型参数中的可为空类型一样高效。

Unfortunately, you're not going to be able to get the Nullable return type AND support for reference types by using generics, unless you specify that you want a Nullable returned when you make the call

public static T Get<T>(this DataRow row, string field)
{
    if (row.IsNull(field))
        return default(T);
    else
        return (T)row[field];
}

and when you call

var id = dr.Get<int?>("user_id");

I didn't test this, just tossed it up here. Give it a shot.

EDIT:

Alternatively, if you really wanted to convert the value types into nullables and still be able to support reference types something like this might work

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];
    }
}

However, it'd require a cast on every usage

var id = dr.Get<string>("username") as string;
var id = (int?)dr.Get<int>("user_id");

This is, however, not going to be nearly as efficient as just accepting the nullable type in the generic type parameters.

谈场末日恋爱 2024-10-24 01:47:43

正如韦斯指出的,你的问题是结构的约束。我希望扩展方法能够在没有约束的情况下工作...

啊,我现在明白了,您正在返回 T? 好吧,我不确定,但是您可以定义一个约束方法的两个变体吗到 struct ,另一个到 class 并返回 T

As Wes points out, your issue is the constraint to struct. I'd expect that extension method to work without constraints...

Ah, I see now, you're returning T? Well, I am not sure but can you define two variants of the method one constraining to struct, the other to class and returning T ?

可爱咩 2024-10-24 01:47:43

像这样的事情怎么样?与您的示例不太一样,但对于引用类型、可为空值类型和不可为空值类型非常有用:

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];
}

How about something like this? Not quite the same as your example, but pretty usable for reference-types, nullable value-types and non-nullable value-types alike:

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];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文