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) 会遇到同样的问题,其中dtDataTable,但明确指定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&lt;T&gt; 扩展方法返回一个IEnumerable&lt;T&gt;,它又使用IEnumerator&lt;T&gt;,而T最终成为Current的类型枚举数的属性,因此传播类型信息。

我怀疑您是否会此时从这些细节中受益,但您可能希望保留此信息,以便在您了解有关该语言的更多信息时进一步参考。您必须了解扩展方法和泛型类型才能掌握这一点。

【讨论】:

是的,我现在看到了。谢谢你的深入解释。【参考方案2】:

这是因为GridView.Rows 属性返回GridViewRowCollection 类型。

在这种情况下,var 无法从用法中推断出该对象将是内部的 DataGridViewRow

来源:GridView.Rows Property

【讨论】:

【参考方案3】:

DataGridViewRow.Rows 是DataGridViewRowCollection 类型,它没有实现IEnumerable&lt;DataGridViewRow&gt;,只有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# 中的对象?

poll不适用于setted var

Perl/CGI 不适用于 /home/user/cgi 但适用于 /var/www/cgi-bin

为啥“重启”操作不适用于 crontab?

CakePhp 2.6.3 不适用于 PHP 7

dplyr 取消引用不适用于过滤器功能