首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >扩展Datarow扩展方法

扩展Datarow扩展方法
EN

Stack Overflow用户
提问于 2017-07-20 03:21:54
回答 2查看 668关注 0票数 2

我正在尝试扩展DataRow扩展的Field方法,以添加一个参数来检查列是否存在:

代码语言:javascript
复制
public static T? FieldValue<T>(
    this DataRow row,
    string columnName,
    bool checkColumn = false) where T : struct

{
    return
        checkColumn
        && !row.Table.Columns.Contains(
                                       columnName)
        ? default(T)
        : row.Field<T>(
                       columnName);
}

这对于int,datetime等很有效。但是,当我尝试将它与string一起使用时,它显示错误:

代码语言:javascript
复制
The type string must be non-nullable

如果数据库中有空值,我也会收到错误:

代码语言:javascript
复制
Cannot cast DBNull.Value to type 'System.Decimal'

有没有一种方法可以无缝地扩展Dataextension?

EN

回答 2

Stack Overflow用户

发布于 2017-07-20 05:52:03

正如Markus所指出的,这里有两个挑战。一个是关于结构与值类型,另一个是关于你必须处理空值的事实。

第二个问题很容易处理:只需像这样向您的实现添加一个?row.Field<T?>(columnName),您的异常就会消失。

然而,第一个问题是一个令人讨厌且经常遇到的问题。我不知道有什么好办法来解决这个问题。还是让我提个建议吧:

根据上面的代码,我假设您很乐意返回Nullable类型,即使对于不可空的列也是如此。下面是你可以做的一些事情,在你已经拥有的基础上支持引用类型,并且仍然避免太多的代码重复:

代码语言:javascript
复制
// value type version
public static T? FieldValueStruct<T>(this DataRow row, string columnName, bool checkColumn = false)
    where T : struct
{
    return row.GetValue(columnName, checkColumn, default(T), row.Field<T? /*with a question mark!!!*/ >);
}

// reference type version
public static T FieldValueClass<T>(this DataRow row, string columnName, bool checkColumn = false)
    where T : class
{
    return row.GetValue(columnName, checkColumn, default(T), row.Field<T>);
}

// shared amongst value and reference type implementation
private static T GetValue<T>(this DataRow row, string columnName, bool checkColumn, T defaultValue, Func<string, T> getter)
{
    return checkColumn && !row.Table.Columns.Contains(columnName)
        ? defaultValue
        : getter(columnName);
}

有了这些代码,您就可以获得所需的功能,但代价是:在调用这些方法时,您需要指定类型参数(就像现在一样),因为类型推断将不起作用(here is why)。

代码语言:javascript
复制
string s;
// no type inference, type parameter must be specified
s = row.FieldValueClass<string>("test");

此外,您还需要在调用中区分值类型版本和引用类型版本,这是很不美观的。为什么我们需要对这些方法使用两个不同的名称?这样做的原因是,您不能通过简单地添加不同的类型约束来重载方法(参见here)。

类型推断主题可以通过使用out参数来解决,然而,这也带来了一系列缺点...

代码语言:javascript
复制
// value type version that works with type inference
public static void FieldValueStruct<T>(this DataRow row, string columnName, out T? value, bool checkColumn = false)
    where T : struct
{
    value = row.GetValue(columnName, checkColumn, default(T), row.Field<T?>);
}

// reference type version that works with type inference
public static void FieldValueClass<T>(this DataRow row, string columnName, out T value, bool checkColumn = false)
    where T : class
{
    value = row.GetValue(columnName, checkColumn, default(T), row.Field<T>);
}

现在,您可以在不使用type参数的情况下调用方法,如下所示:

代码语言:javascript
复制
string s;
// with type inference, doesn't work with properties, though, only with fields
row.FieldValueClass("test", out s);

不幸的是,这不适用于属性-仅适用于字段。

你看,这个世界是邪恶的,有时候,我们对此无能为力。;)

基于您的评论的更新:

下面的代码稍微改变了你的语义,但也许这没什么问题:

代码语言:javascript
复制
public static T FieldValue<T>(this DataRow row, string columnName, bool checkColumn = false)
{
    return checkColumn && !row.Table.Columns.Contains(columnName)
        ? default(T)
        : row.Field<T>(columnName);
}

调用此方法需要如下所示:

代码语言:javascript
复制
// this will return 0 if the column is not available, a null value from the database will cause an exception
int i = r.FieldValue<int>("test");
// this will return null if the column is not available, a null value from the database would be ok
int? iNullable = r.FieldValue<int?>("test");
// this will return null if the column is not available, a null value from the database would be ok
string s = r.FieldValue<string>("test");
票数 2
EN

Stack Overflow用户

发布于 2017-07-20 03:30:38

第一条错误消息的原因是where-constraint:

代码语言:javascript
复制
where T : struct

此约束要求用作类型参数的每个类型T都是值类型。string是一个引用类型,因此出现错误消息。为了解决这个问题,如果你不需要这个约束,你应该删除它。

对于空值问题,您应该检查列是否为空(如果存在),在这种情况下还应返回default(T)。可以使用DataRow.IsNull方法检查单元格是否为空。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45199333

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档