2010-10-28 26 views
7

Tôi có một lớp với một API cho phép tôi hỏi các đối tượng cho đến khi nó ném một số IndexOutOfBoundsException.Trình lặp .NET để bọc ném API

Tôi muốn đưa nó vào một trình lặp, để có thể viết mã sạch hơn. Tuy nhiên, tôi cần phải nắm bắt những ngoại lệ để ngăn chặn lặp:

static IEnumerable<object> Iterator(ExAPI api) { 
    try { 
     for(int i = 0; true; ++i) { 
      yield return api[i]; // will throw eventually 
     } 
    } 
    catch(IndexOutOfBoundsException) { 
     // expected: end of iteration. 
    } 
} 

Nhưng ...

Khi sử dụng với biểu hiện, một tuyên bố yield return không thể xuất hiện trong một khối bắt hoặc trong một thử khối có một hoặc nhiều mệnh đề bắt. Để biết thêm thông tin , hãy xem Xử lý ngoại lệ Báo cáo (Tham chiếu C#) .Báo cáo (Tham chiếu C#). (từ số msdn)

Tôi vẫn có thể bọc api này như thế nào?

+0

@Coding Gorilla: đó là điểm: không. Nó bắt đầu từ số không và tăng lên. – xtofl

Trả lời

14

Bạn chỉ cần di chuyển các tuyên bố yield return bên ngoài của khối try, như thế này:

static IEnumerable<object> Iterator(ExAPI api) { 
    for(int i = 0; true; ++i) { 
     object current; 
     try { 
      current = api[i]; 
     } catch(IndexOutOfBoundsException) { yield break; } 

     yield return current; 
    } 
} 
+0

mặc dù bạn không cần một "if (current! = Null) yield return current"? –

+0

oh chờ đợi im dumb tôi bị mất nghỉ năng suất. –

+0

Tài liệu báo cáo 'yield break' bị bỏ đi trên msdn ... Cảm ơn bạn đã chỉ ra! – xtofl

0

Chỉ cần sắp xếp lại các mã:

static IEnumerable<object> Iterator(ExAPI api) { 
    bool exceptionThrown = false; 
    object obj = null; 
    for(int i = 0; true; ++i) { 
     try { 
      obj = api[i]; 
     } 
     catch(IndexOutOfBoundsException) { 
      exceptionThrown = true; 
      yield break; 
     } 

     if (!exceptionThrown) { 
      yield return obj; 
     } 
    } 
} 
+0

Điều này sẽ không bao giờ dừng lại. – SLaks

+0

Không, tôi đã viết quá nhanh Tôi đoán .... Dù sao, câu trả lời của bạn dưới đây là sạch hơn và tốt hơn :-) – AHM

+0

Bây giờ bạn có một biến vô dụng. – SLaks

4

Bạn có thể bọc các hoạt động đơn giản của việc đối tượng vào một chức năng riêng biệt. Bạn có thể bắt ngoại trừ trong đó:

bool TryGetObject(ExAPI api, int idx, out object obj) 
{ 
    try 
    { 
     obj = api[idx]; 
     return true; 
    } 
    catch(IndexOutOfBoundsException) 
    { 
     return false; 
    }   
} 

Sau đó, gọi hàm đó và chấm dứt nếu cần thiết:

static IEnumerable<object> Iterator(ExAPI api) 
{ 
    bool abort = false; 

    for(int i = 0; !abort; ++i) 
    { 
     object obj; 
     if(TryGetObject(api, i, out obj)) 
     { 
      yield return obj; 
     } 
     else 
     { 
      abort = true; 
     } 
    } 
} 
+0

Tôi không thực sự là người hâm mộ của phương pháp này. Nếu api chỉ được truy cập trong phương thức này, một phương thức riêng biệt để lấy đối tượng là thừa. –

+0

@Joshua: nhưng một lambda có thể làm việc ... – xtofl

0

Nếu bạn không thể kiểm tra bờ cõi của các đối tượng ở tất cả, bạn có thể làm điều gì đó như thế này

static IEnumerable<object> Iterator(ExAPI api) 
{ 
List<object> output = new List<object>(); 
    try 
{ 
    for(int i = 0; true; ++i) 
    output.Add(api[i]); 
    } 
    catch(IndexOutOfBoundsException) 
{ 
    // expected: end of iteration. 
    } 
return output; 
} 

mặc dù bây giờ im nhìn vào đây, câu trả lời ở trên là tốt hơn tôi tin. Một SLaks được đăng.

+0

Thật vậy: ý định của tôi là không điền vào một container, mà là cung cấp một iterator. – xtofl

0
static IEnumerable<object> Iterator(ExAPI api) 
    { 
     int i = 0; 
     while (true) 
     { 
      Object a; 
      try 
      { 
       a = api[i++]; 
      } 
      catch (IndexOutOfBoundsException) 
      { 
       yield break; 
      } 
      yield return a; 
     } 
    } 
Các vấn đề liên quan