2010-08-11 28 views
9

Loại bê tông cho IEnumerable<string> là gì?Loại hình cụ thể nào mang lại lợi tức 'lợi nhuận'?

private IEnumerable<string> GetIEnumerable() 
{ 
    yield return "a"; 
    yield return "a"; 
    yield return "a"; 
} 
+1

Đây là một đường cú pháp. rất nhiều đang xảy ra dưới mui xe. Cách nhanh hơn để xem nó là sử dụng bộ phản xạ. Về cơ bản nó tạo ra một lớp giữ trạng thái và trả về "a" khi 'GetNext()' hoặc một cái gì đó như thế được gọi. –

+0

@Timwi cảm ơn chỉnh sửa :) – stacker

Trả lời

7

Đây là loại do trình biên dịch tạo. Trình biên dịch tạo ra một triển khai thực hiện IEnumerator<string> trả về ba giá trị "a" và một lớp xương IEnumerable<string> cung cấp một trong các phương thức này theo phương thức GetEnumerator của nó.

Mã được tạo ra trông một cái gì đó giống như * này:

// No idea what the naming convention for the generated class is -- 
// this is really just a shot in the dark. 
class GetIEnumerable_Enumerator : IEnumerator<string> 
{ 
    int _state; 
    string _current; 

    public bool MoveNext() 
    { 
     switch (_state++) 
     { 
      case 0: 
       _current = "a"; 
       break; 
      case 1: 
       _current = "a"; 
       break; 
      case 2: 
       _current = "a"; 
       break; 
      default: 
       return false; 
     } 

     return true; 
    } 

    public string Current 
    { 
     get { return _current; } 
    } 

    object IEnumerator.Current 
    { 
     get { return Current; } 
    } 

    void IEnumerator.Reset() 
    { 
     // not sure about this one -- never really tried it... 
     // I'll just guess 
     _state = 0; 
     _current = null; 
    } 
} 

class GetIEnumerable_Enumerable : IEnumerable<string> 
{ 
    public IEnumerator<string> GetEnumerator() 
    { 
     return new GetIEnumerable_Enumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

Hoặc có thể, như SLaks nói trong câu trả lời của mình, hai ngôn ngữ này kết thúc trong cùng một lớp. Tôi đã viết điều này dựa trên bộ nhớ trống của tôi về mã được tạo ra mà tôi đã xem trước đó; thực sự, một lớp sẽ đủ, vì không có lý do nào mà chức năng trên yêu cầu hai.

Trong thực tế, đến để suy nghĩ về nó, hai triển khai thực sự nên sụp đổ trong một lớp duy nhất, như tôi chỉ nhớ đến các chức năng sử dụng yield báo cáo phải có một kiểu trả về của hoặcIEnumerable<T>hayIEnumerator<T> .

Dù sao, tôi sẽ cho phép bạn thực hiện chỉnh sửa mã cho những gì tôi đăng về tinh thần.

* Điều này hoàn toàn dành cho mục đích minh họa; Tôi không tuyên bố về độ chính xác thực sự của nó. Nó chỉ để chứng minh một cách tổng quát như thế nào trình biên dịch làm những gì nó làm, dựa trên các bằng chứng tôi đã thấy trong các cuộc điều tra của riêng tôi.

+2

Hơn nữa, loại trình biên dịch tạo ra sẽ có tên ' d__0' trong ví dụ của bạn. (Có, '<' and '>' là một phần của tên * *. Bạn không thể viết tên kiểu như vậy trong C#, nhưng nó có giá trị trong CLR.) Kiểu được lồng bên trong kiểu khai báo 'GetIEnumerable() 'phương thức. – Timwi

7

Trình biên dịch sẽ tự động tạo một lớp thực hiện cả hai IEnumerable<T>IEnumerator<T> (trong cùng một lớp).

Jon Skeet has a detailed explanation.

+0

+1 cho liên kết. – stacker

+1

Vui lòng thêm các phần liên quan của liên kết vào câu trả lời của bạn –

2

Việc thực hiện cụ thể của IEnumerable<string> trả về bởi phương pháp này là một loại vô danh tạo ra bởi trình biên dịch

Console.WriteLine(GetIEnumerable().GetType()); 

Prints:

YourClass+<GetIEnumerable>d__0 
Các vấn đề liên quan