【问题标题】:var won't work with DataGridViewRowvar 不适用于 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) 可以正常工作

标签: c# .net var datagridviewrow


【解决方案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.RowsDataGridViewRowCollection 类型,它没有实现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 推断类型,因此代码完全按照您自己指定的方式进行编译。它实际上只是一种语法糖,可以让您省去输入长类名(当然还有匿名类型)。
    猜你喜欢
    • 2018-05-30
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    相关资源
    最近更新 更多