我看到一些属性允许蜜蜂casted implicitly
。就像DataTable.Rows
和DataRow
中的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如何设计的误解。
答案 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,它实现了DataRowCollection
和ICollection
,但它从未更新以实现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
, 是编译器可以在编译时检查的内容。由于它们是类,因此除非存在继承关系或自定义转换运算符,否则它将失败。既然都不存在:它会失败。