【问题标题】:Objects of a specific type in foreach from an IEnumerable来自 IEnumerable 的 foreach 中特定类型的对象
【发布时间】:2011-08-23 18:22:32
【问题描述】:

我正在使用仅实现非泛型 IEnumerableICollection 的遗留集合对象。当我尝试将此对象与 foreach 一起使用时,该对象究竟会发生什么情况?在 foreach 表达式的 LHS 上提供更具体的类型?

// LegacyFooCollection implements non-generic IEnumerable
LegacyFooCollection collection = GetFooCollection();
foreach (Foo f in collection)
{
    // etc.
}

我知道(因为我已经尝试过)当collection 中的所有内容确实是Foo 类型时这是安全的,但如果失败会发生什么?

【问题讨论】:

  • 我认为在这种情况下它会为空。

标签: c# generics foreach ienumerable


【解决方案1】:

C# 编译器为您隐式执行转换。就铸造而言(但在这些术语中1)相当于:

foreach (object tmp in collection)
{
    Foo f = (Foo) tmp;
    ...
}

请注意,泛型集合也会发生这种情况:

List<object> list = new List<object> { "hello", "there", 12345 };

// This will go bang on the last element
foreach (string x in list) 
{
}

C# 4 规范的第 8.8.4 节对此进行了详细说明。

如果您使用 .NET 3.5 或更高版本并且只想选择适当类型的项目,则可以使用 Enumerable.OfType

LegacyFooCollection collection = GetFooCollection();
foreach (Foo f in collection.OfType<Foo>())
{
    // etc.
}

这对于 LegacyFooCollection 可能不是必需的,但当您尝试查找(例如)表单中的所有 TextBox 控件时,它会很有用。


1 区别在于:

  • 在您的原始代码中,f 是只读的;在“转换”中它是可写的
  • 在您的原始代码中,如果您捕获 f,您将(当前)在所有迭代中捕获单个变量,而不是在“转换”中每次迭代捕获一个单独的变量

【讨论】:

  • 不,实际上,它不等于那个。首先,语法是foreach (object tmp in collection)。其次,您可以在您的示例中将您想要的任何内容分配给f,而在OP 的示例中您不能这样做,因为他的f 是一个foreach 迭代变量。 (一个微妙但重要的区别。)
  • @cdhowie:是的,我的意思是包括关于阅读在线的部分。如果变量被捕获,也会有所不同。修正了“in”的“=”的错字(这很明显只是一个错字——以后可以随意编辑这些东西)。
【解决方案2】:

此代码将创建可枚举的每个元素到Foo 的运行时类型转换(强制转换)。因此,如果您执行foreach (string f in collection),您将在运行时获得ClassCastException,这是它第一次尝试将Foo 引用转换为String 引用。

【讨论】:

    【解决方案3】:

    每次都会投射。 foreach 循环只是使用 IEnumerator 方法。

    【讨论】:

      【解决方案4】:

      ForEeach 中的短投:

      foreach (MenuItem menuItem in treeView.ContextMenu.Items.Cast<object>().OfType<MenuItem>()
      {
          // Do stuff
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-07
        • 1970-01-01
        • 2014-07-22
        • 2021-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多