如何实现隐式转换?

时间:2014-07-02 10:20:09

标签: c# properties casting

我看到一些属性允许蜜蜂casted implicitly。就像DataTable.RowsDataRow中的DateRowView一样。

void DemoFunc()
{
    DataTable dtTable = new DataTable();

    foreach (DataRow row in dtTable.Rows)
    {


    }

    foreach (DataRowView row in dtTable.Rows)
    {

    }
}

我可以在自己的代码中使用此行为。有人知道一个简单的例子来理解它是如何工作的吗?

修改

我的目标是什么? 我想知道是否有可能设计这样的代码:

Void DemoFunc2()
{

MyObject myObjec = new MyObject()

OtherObject otherObject = myObject.Property;
DifferentObject differentObject = myObject.Property;

}

属性是否可以返回不同的对象类型?

编辑2:

在这个问题中混合了两个不同的东西。一旦想知道如何获得具有两种不同返回类型的属性,基于对DataTable.Rows如何设计的误解。

1 个答案:

答案 0 :(得分:3)

简单:不起作用:

  

未处理的异常:System.InvalidCastException:无法转换类型的对象   '的System.Data.DataRow'输入' System.Data.DataRowView'。

但是,foreach适用于在某些情况下允许隐式强制转换的模式。他们是否有效。在此示例中,编译器无法检查它,因为.Rows公开了基于object的迭代器(在本例中为IEnumerable / IEnumerator,但即使这样也不严格必要)。

更一般地说,存在隐式转换运算符,但仍然不适用于基于object的迭代器,因为运算符仅适用于静态已知类型(除非使用{{1} })。

dynamic方法允许访问超过GetEnumerator()的内容的情况下,编译器可以告诉我们:

object

编译器添加错误:

  

错误1无法转换类型' System.Data.DataRow'到' System.Data.DataRowView'

虽然在这种情况下,如果已定义,它至少会允许使用隐式运算符。他们不是。


更多细节:

为什么要编译?

foreach (DataRowView row in dtTable.AsEnumerable()) { } 的输入为.Rows。由于这可以追溯到.NET 1.1,它实现了DataRowCollectionICollection,但它从未更新以实现IEnumerable。同样,IEnumerable<DataRow>方法返回GetEnumerator() - 不是更具体的内容。

IEnumerator(与IEnumerator不同)的问题是IEnumerator<T>仅作为.Current输入,因为.NET 1.1和C#1.2没有&#39}。有泛滥。如果你不得不这样做会非常尴尬:

object

为方便起见,语言允许您隐式执行,即上述内容大致相同:

foreach(object tmp in table.Rows)
{
    DataRowView row = (DataRowView)tmp; // this is our known-bad code
    // ...

实际的内容如下:

foreach(DataRowView row in table.Rows) // this is our known-bad code
{
    // ...

请注意{ IEnumerator iter = table.Rows.GetEnumerator(); // note this ^^^ is disposed after the loop if IDisposable; not shown while(iter.MoveNext()) { DataRowView row = (DataRowView) iter.Current; // .Current is: object // ... } } object的演员表是怎样的?如果从DataRowView返回的内容实际上不是.Current(并且:它不是),则只有在执行强制转换时在运行时时才会失败。如果我们使用DataRowView代替DataRow做同样的事情,那么它就会成功。

请注意,DataRowView模式实际上并不依赖foreach;任何类型都可以使用IEnumerator方法,并返回具有更强(类型)GetEnumerator()实现的自定义迭代器类型。如果.Current已完成此操作,则** DataRowCollection的代码将失败。这可以是完全自定义的迭代器,也可以只是DataRowView / IEnumerable<DataRow>。考虑完全假设:

IEnumerator<DataRow>

现在使用此构造,我们可以看到我们正在从{ IEnumerator<DataRow> iter = table.Rows.GetEnumerator(); // note this ^^^ is disposed after the loop if IDisposable; not shown while(iter.MoveNext()) { DataRowView row = (DataRowView) iter.Current; // .Current is: DataRow // ... } } 转换为DataRow 是编译器可以在编译时检查的内容。由于它们是类,因此除非存在继承关系或自定义转换运算符,否则它将失败。既然都不存在:它会失败。