2010-09-15 32 views
27

Tại sao điều này tạo ra một lỗi biên dịch:Tại sao biểu thức khởi tạo bộ sưu tập yêu cầu IEnumerable được triển khai?

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" }; 
    } 
} 

nhưng điều này không:

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" }; 
    } 
} 

lý do để hạn chế initializers bộ sưu tập là gì - đó là cú pháp đường cho một cuộc gọi đến một phương pháp Add - đối với các lớp triển khai giao diện không có phương thức an Add và phương thức nào không được sử dụng?

+4

Có một số điều trong C# tôi không nhận được. Đây là một trong số họ. Khác là 'foreach'. – leppie

+2

@leppie: Bạn không "nhận được" gì về việc tìm kiếm? –

+1

@Jon Skeet: Tôi nghĩ rằng leppie đề cập đến thực tế là trình biên dịch chỉ yêu cầu sự hiện diện của một phương thức mà không yêu cầu một giao diện cụ thể là loại hành vi gõ-vịt bằng ngôn ngữ được đánh máy mạnh. –

Trả lời

23

An đối tượng bộ khởi tạo không; bộ sưu tập khởi chạy. Nó để nó được áp dụng cho các lớp thực sự đại diện cho các bộ sưu tập, chứ không chỉ là các lớp tùy ý có phương thức Add. Tôi phải thừa nhận rằng mỗi khi tôi thường xuyên "thực hiện" IEnumerable một cách rõ ràng, chỉ để cho phép người khởi tạo bộ sưu tập - nhưng đã ném một số NotImplementedException từ GetEnumerator().

Lưu ý rằng sớm trong sự phát triển của C# 3, người khởi tạo bộ sưu tập phải triển khai ICollection<T>, nhưng điều đó đã bị phát hiện quá hạn chế. Mads Torgersen blogged about this change và lý do đằng sau yêu cầu IEnumerable, quay lại năm 2006.

+0

Sẽ không cùng một đối số áp dụng cho cú pháp truy vấn LINQ? Tuy nhiên, nó không yêu cầu bất kỳ giao diện nào, và thậm chí cho phép “biến vòng lặp” là một tên kiểu và “Where/Select” là một phương thức tĩnh ... – Timwi

+0

@Timwi: Sắp xếp, mặc dù ít có khả năng là một truy vấn biểu thức sẽ thực sự biên dịch theo kiểu tùy ý hơn bộ khởi tạo bộ sưu tập - tôi nghi ngờ rằng 'Add' có nhiều ý nghĩa khác" hơn 'các phương thức' Where' và 'Select' với các kiểu tham số thích hợp. Cũng lưu ý rằng có * không * một giao diện thích hợp mà có thể đã được áp dụng để kiểm tra các truy vấn LINQ sanity - suy nghĩ về Reactive Extnesions, mà không có bất kỳ giao diện chung với LINQ to Objects ... –

+6

Không phải một ngày trôi qua mà không có tôi mong muốn .NET 2 là phiên bản đầu tiên ... 90% của tất cả các cruft trong .NET dường như đến từ sự tồn tại của .NET 1 với những thứ không chung chung của nó ... –

Các vấn đề liên quan