var 不适用于 DataGridViewRow
Posted
技术标签:
【中文标题】var 不适用于 DataGridViewRow【英文标题】:var won't work with DataGridViewRow 【发布时间】:2015-06-21 22:58:41 【问题描述】:我是 C# 新手,对“var”的使用有疑问
当我使用以下代码时,一切正常
foreach(DataGridViewRow row in myGrid.Rows)
if (row.Cells[2].Value.ToString().Contains("51000"))
row.Cells[0].Value = "X";
但是当我将 DataGridViewRow
更改为 var
时,我得到了错误提示
'object' 不包含'Cells' 的定义并且没有扩展名 接受“object”类型的第一个参数的方法“Cells”可以是 找到(您是否缺少 using 指令或程序集引用?)
【问题讨论】:
听起来 c# 试图为 DataGridViewRow 暗示错误的类型,当 myGrid.Rows 的定义不明确时会发生这种情况foreach (var row in dt.Rows)
会遇到同样的问题,其中dt
是DataTable
,但明确指定foreach (DataRow row in dt.Rows)
可以正常工作
【参考方案1】:
myGrid.Rows
的类型为 DataGridViewRowCollection
。
这东西很老了,它的定义是:
public class DataGridViewRowCollection : ICollection, IEnumerable, IList
您看到非通用接口了吗?这个类可以实现IList<DataGridViewRow>
,然后var
就可以工作,但它是遗留的。
IEnumerable
没有传达有关项目类型的信息,GetEnumerator
函数在这里没有帮助,因为它返回一个 IEnumerator
,而它可以返回一个 IEnumerator<DataGridViewRow>
。
本质上,C# 编译器寻找一个 GetEnumerator
函数,该函数返回一个对象,该对象具有一个 MoveNext
函数和一个 Current
属性(或一个 IEnumerable<T>
/IEnumerable
接口当明确实施时)。这种duck-typing 方法是出于历史原因,它在泛型被引入语言之前就已经存在。 foreach
循环变量与Current
属性的类型相同。在IEnumerator
(非泛型变体)中,Current
的类型为object
。
明确指定类型:
foreach (DataGridViewRow row in myGrid.Rows)
简单地将Current
的返回值转换为DataGridViewRow
,因为缺少更好的机制。
如果您真的想在此处使用 var
关键字,也可以使用 LINQ 来实现相同的效果:
foreach (var row in myGrid.Rows.Cast<DataGridViewRow>())
这是可行的,因为Enumerable.Cast<T>
扩展方法返回一个IEnumerable<T>
,它又使用IEnumerator<T>
,而T
最终成为Current
的类型枚举数的属性,因此传播类型信息。
我怀疑您是否会此时从这些细节中受益,但您可能希望保留此信息,以便在您了解有关该语言的更多信息时进一步参考。您必须了解扩展方法和泛型类型才能掌握这一点。
【讨论】:
是的,我现在看到了。谢谢你的深入解释。【参考方案2】:这是因为GridView.Rows
属性返回GridViewRowCollection
类型。
在这种情况下,var
无法从用法中推断出该对象将是内部的 DataGridViewRow
。
来源:GridView.Rows Property
【讨论】:
【参考方案3】:DataGridViewRow.Rows
是DataGridViewRowCollection 类型,它没有实现IEnumerable<DataGridViewRow>
,只有IEnumerable
。而object
是当您没有为row
指定强制转换为DataGridViewRow
时哪个编译器可以推断出的最佳猜测
【讨论】:
正确...但解释为什么只实现IEnumerable
会导致类型object
被推断...
正确。提问者预计,在 2015 年,我们将度过旧的非泛型 .NET 1 天(.NET 2 和泛型于 2005 年出现)。但是DataGridViewRowCollection
,没有。【参考方案4】:
如果将 DataGridViewRow 更改为 Var C# 不确定是否有一个名为单元格的数组。要解决此问题,您可以将 var 强制转换为 DataGridViewRow,但如果您知道该类型,则使用该类型几乎总是更好,请在线查找类型安全以获取更多信息。
【讨论】:
我同意使用类型总是更好。我只是在修改方法,想知道为什么 var 不起作用,但我现在明白了 - 谢谢var
是类型安全的;可用时使用它没有任何问题。 compiler 推断类型,因此代码完全按照您自己指定的方式进行编译。它实际上只是一种语法糖,可以让您省去输入长类名(当然还有匿名类型)。以上是关于var 不适用于 DataGridViewRow的主要内容,如果未能解决你的问题,请参考以下文章
TryParse 适用于 var 但不适用于 C# 中的对象?