2012-12-19 60 views
5

假設我有以下方法。在某些來到從迭代器塊返回單個元素 - 迭代器不能包含返回語句

public IEnumerable<ValidationResult> Validate(UserLoginCommand command) 
    { 
     User user = userRepository.Get(u => u.Email == command.UserEmail); 
     if(user != null) 
     { 
      if(!user.Activated) 
      { 
       return new IEnumerable<ValidationResult>() {new ValidationResult("NotActived", Resources.UserNotActivated)}; 
      } 

      if(user.IsPasswordIncorrent) 
      { 

       yield return new ValidationResult("IncorrectPassword", Resources.IncorrentPassword); 

      } 

     } 
    } 

實際情況實際上是一個有點複雜,但我已經留下了很多用於說明目的。

點是在某些情況下,我想迭代繼續收集多個錯誤...但在其他情況下,有一個致命的錯誤,我只是想返回一個錯誤,但它不會讓我:

Iterator cannot contain return statement 

我該怎麼辦?

+2

我認爲錯誤信息非常明確。你不能混合'yield'和'return',因爲函數的執行被推遲到迭代器被調用。我建議擺脫「收益率」,並建立自己的枚舉。我希望Jon Skeet或者Eric Lippert會在這裏談談爲什麼編譯器不能處理這種情況。 –

回答

10

如果你只是想返回大小爲一的集合,你可以這樣做:

if(!user.Activated) 
{ 
    yield return new ValidationResult("NotActived", Resources.UserNotActivated); 
    yield break; 
} 
+0

謝謝,這是我需要的簡單解決方案。 – parliament

3

這個return語句不應該是一個yield嗎?

yield return ValidationResult("NotActived", Resources.UserNotActivated); 

如果你真的需要返回一個集合,你可以yield return集合,太(如有的話),它因爲你只有一個只是沒有必要的。

此外,要停止明確列舉的情況下,你可以使用yield break;

3

由於由錯誤消息指示,您不能將yield return語句和return語句混合成單一方法。

你有兩種常用的方法:

  1. 的方法應該是急切地評估;您應該使用全部return語句,找到將所有yield語句轉換爲回報的方法。
  2. 該方法應使用延遲執行,找到一種方法將所有return語句轉換爲yield語句。

就你而言,它可能是#2,但在其他情況下可能是適當的。

現在,如何把yieldreturn

包住單個元素成某種形式的收集和返回:

return new[]{ someItemToReturn }; 

return Enumerable.Repeat<T>(someItemToReturn, 1); 

現在,如何將return變成yield

foreach(var item in collectionYouWereReturning) 
    yield return item; 

您可以使用yield break;來指示即使方法未達到其自然結束,序列也已結束。請注意,yield break;應該很少使用。使用它很多代碼味道(但這似乎是一個適當的情況下)。

現在,理想情況下,我們會有一個yield foreach某種關鍵字,以便您可以在迭代器塊內生成一個集合,但是至今尚未向該語言添加這樣的關鍵字。

+0

感謝您的迴應,我學到了一些有用的東西,將來會有用,但在這種情況下,我更喜歡保持我在任何地方都使用的相同模式(收益回報),但在特殊情況下只返回一個元素。保羅菲利普斯的答案很簡單並且很有效。 Upvote肯定。 – parliament