【问题标题】:Why does a collection initializer expression require IEnumerable to be implemented?为什么集合初始化表达式需要实现 IEnumerable?
【发布时间】:2010-09-15 10:08:45
【问题描述】:

为什么会产生编译错误:

class X { public void Add(string str) { Console.WriteLine(str); } }

static class Program
{
    static void Main()
    {
        // error CS1922: Cannot initialize type 'X' with a collection initializer
        // because it does not implement 'System.Collections.IEnumerable'
        var x = new X { "string" };
    }
}

但事实并非如此:

class X : IEnumerable
{
    public void Add(string str) { Console.WriteLine(str); }
    IEnumerator IEnumerable.GetEnumerator()
    {
        // Try to blow up horribly!
        throw new NotImplementedException();
    }
}

static class Program
{
    static void Main()
    {
        // prints “string” and doesn’t throw
        var x = new X { "string" };
    }
}

将集合初始值设定项(用于调用 Add 方法的语法糖)限制为实现接口的类的原因是什么,该接口具有Add 方法和哪个没用?

【问题讨论】:

  • C# 中有些东西我只是不明白。这是其中之一。另一个是foreach
  • @leppie:你对 foreach 没有“了解”什么?
  • @Jon Skeet:我认为 leppie 指的是编译器只需要一个方法的存在而不需要一个特定的接口,这是一种强类型语言中的鸭子类型行为。
  • @0xA3:这主要是因为 C# 1 中缺少泛型。这种鸭子类型允许使用值类型的强类型迭代器无需装箱。我怀疑如果它以泛型开头,它就不会出现在 C# 中,尽管它仍然用于避免在 List<T> 上使用 foreach 时对迭代器进行装箱。
  • @Jon Skeet:它的作用超出了人们的预期。我确实“明白”了它,我只是不明白为什么。但正如你所说,这可能与泛型有关。

标签: c# syntax language-design


【解决方案1】:

object 初始化器没有; collection 初始化器会。这样它就可以应用于真正代表集合的类,而不仅仅是具有Add 方法的任意类。我不得不承认,我经常明确地“实现”IEnumerable,只是为了允许集合初始化器——但是从GetEnumerator() 抛出了一个NotImplementedException

请注意,在 C# 3 开发的早期,集合初始值设定项必须实现 ICollection<T>,但被发现限制性太强。 Mads Torgersen blogged about this change,以及要求 IEnumerable 背后的原因,早在 2006 年。

【讨论】:

  • 难道不是同样的参数适用于 LINQ 查询语法吗?然而它不需要任何接口,甚至允许“迭代器变量”作为类型名称,“Where/Select”作为静态方法......
  • @Timwi:有点,尽管查询表达式实际上不太可能针对任意类型编译而不是集合初始值设定项——我怀疑AddWhere 有更多“其他含义”和 Select 具有适当参数类型的方法。另请注意,没有一个合适的接口可以应用于完整性检查 LINQ 查询 - 想想 Reactive Extnesions,它与 LINQ to Objects 没有任何通用接口...
  • 没有一天没有我希望 .NET 2 是第一个版本... .NET 中 90% 的杂乱无章似乎来自 .NET 1 的存在及其非泛型东西...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 2014-07-30
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
相关资源
最近更新 更多