如何消除c#中的强类型

本文关键字:强类型 何消 | 更新日期: 2023-09-27 18:14:19

假设我必须将从数据库读取的内容转换为对象。我可以这样写:

public class Foo {
    int a;
    DateTime b;
    float c;
    public Foo(int a, DateTime b, float c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    internal Foo(DataRow dr) {
        this.a = (int) dr["a"];
        this.b = (DateTime) dr["b"];
        this.c = (float) dr["c"];
    }
}

是否可以使用dynamic关键字,自动删除类型检查和强制类型转换?理想情况下,它只适用于internal构造函数。

如何消除c#中的强类型

你是说这样吗?

public class Foo {
    dynamic a;
    dynamic b;
    dynamic c;
    public Foo(int a, DateTime b, float c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    internal Foo(DataRow dr) {
        this.a = dr["a"];
        this.b = dr["b"];
        this.c = dr["c"];
    }
}

当然,如果你真的很讨厌强制类型转换,你可以这样做,然后编译器不再是你最好的朋友,以防止你搬起石头砸自己的脚。

如果您主要关心的是摆脱丑陋的强制转换,那么另一种选择是使用DataRowExtensions.Field扩展方法。

提供对指定行中每个列值的强类型访问。

使用例子:

public class Foo {
    int a;
    DateTime b;
    float c;
    public Foo(int a, DateTime b, float c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
    internal Foo(DataRow dr) {
        this.a = dr.Field<int>("a");
        this.b = dr.Field<DateTime>("b");
        this.c = dr.Field<float>("c");
    }
}

你可以在DataRow周围实现一个动态包装(警告:未经测试的代码)

public class DynamicDataRow : DynamicObject
{
    private DataRow _dataRow;
    public DynamicDataRow(DataRow dataRow)
    {
        if (dataRow == null)
            throw new ArgumentNullException("dataRow");
        this._dataRow = dataRow;
    }
    public DataRow DataRow
    {
        get { return _dataRow; }
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;
        if (_dataRow.Table.Columns.Contains(binder.Name))
        {
            result = _dataRow[binder.Name];
            return true;
        }
        return false;
    }
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (_dataRow.Table.Columns.Contains(binder.Name))
        {
            _dataRow[binder.Name] = value;
            return true;
        }
        return false;
    }
}

然后按如下方式修改内部构造函数:

internal Foo(DynamicDataRow ddr) {
    dynamic dr = ddr;
    this.a = dr.a;
    this.b = dr.b;
    this.c = dr.c;
}

命名
var foo = new Foo(new DynamicDataRow(someDataRowObject));

与sstan的答案不同,您将失去编译时类型检查的所有好处。这听起来像是一件非常糟糕的事情,但实际上它并没有那么糟糕,因为即使使用DataRowExtensions.Field<T>扩展方法,类型检查仍然在运行时发生,因为编译器没有办法检查数据库中列的数据类型是否与您试图填充该信息的字段相匹配。无论哪种方式都会有运行时类型检查