2012-08-13 149 views
0

我試圖執行下面的代碼(在LINQPad),和我的LINQ語句得到一個錯誤不能轉換UserQuery枚舉枚舉

不能鍵入System.Collections.Generic.IEnumerable<UserQuery.ResultCode>隱式轉換爲UserQuery.ResultCode

爲什麼?

下面是代碼:

public enum ResultCode { 
    Big, 
    Bad, 
    Messy 
} 

public class ValidationResult { 
    public bool IsValid = false; 
    public ResultCode Code; 

    public override string ToString(){ 
     return String.Format("IsValid: {0}, Code: {1}",IsValid, Code); 
    } 
} 

public class RuleMap { 
    public Func<bool> Fact; 
    public ResultCode Code; 
    public List<int> Actions; 
} 


public class RulesProcessor{ 

    List<RuleMap> rules; 

    public RulesProcessor(){ 
     rules = new List<RuleMap>{ 
      new RuleMap {Fact = CheckLeft, Code = ResultCode.Big, 
       Actions = new List<int> {2, 3} 
      }, 
      new RuleMap {Fact = CheckRight, Code = ResultCode.Bad, 
       Actions = new List<int> {1, 2} 
      }, 
      new RuleMap {Fact = CheckDown, Code = ResultCode.Messy, 
       Actions = new List<int> {1, 3} 
      }, 
     }; 
    } 

    public bool CheckLeft(){ 
     return true; 
    } 

    public bool CheckRight(){ 
     return false; 
    } 

    public bool CheckDown(){ 
     return true; 
    } 

    public ValidationResult EvaluateRulesOnAction(int actionType){ 

     ValidationResult result = new ValidationResult(); 

     ResultCode badRule = from foo in rules 
           where !foo.Fact() && foo.Actions.Contains(actionType) 
           select foo.Code; 


     if (badRule != null){ 
      result.Code = badRule; 
     }else{ 
      result.IsValid = true; 
     } 

     return result; 
    } 

} 

void Main() 
{ 
    var foo = new RulesProcessor(); 

    foo.EvaluateRulesOnAction(1).Dump(); 
    foo.EvaluateRulesOnAction(3).Dump(); 
} 

回答

0

的原因是,形式from x in y select x的每LINQ查詢返回的IEnumerable<TypeOfX>

如果你確信可以有最多一個壞的規則,你可以在你的代碼改成這樣:

ResultCode badRule = (from foo in rules 
         where !foo.Fact() && foo.Actions.Contains(actionType) 
         select foo.Code).SingleOrDefault(); 

如果可以有不止一個壞的規則,但你只有在興趣第一個,使用此:

ResultCode badRule = (from foo in rules 
         where !foo.Fact() && foo.Actions.Contains(actionType) 
         select foo.Code).FirstOrDefault(); 

的「OrDefault」在這兩個查詢表明您想擁有返回類型的default value。對於參考類型,這是null

但是,在您的代碼中,查詢返回類型爲ResultCode的枚舉。枚舉不能是null,因此查詢後面的if永遠不會產生預期的結果,因爲badRule == null總是false

您應該將代碼改成這樣:

var badRule = (from foo in rules 
       where !foo.Fact() && foo.Actions.Contains(actionType) 
       select foo).FirstOrDefault(); 

if (badRule != null){ 
    result.Code = badRule.Code; 
}else{ 
    result.IsValid = true; 
} 
+0

在這種情況下,我想...(從規則中的foo ...)FirstOrDefault ...並且如果沒有任何內容返回null。那麼如何?當沒有規則匹配時,當前'FirstOrDefault'返回一個非空值。 – 2012-08-13 18:14:26

+0

@BrentArias:你爲什麼這麼想? FirstOrDefault特別是返回沒有任何內容匹配的'null'的版本。更確切地說,它返回'default(ResultCode)',它是'null'用於引用類型。但是,當你返回一個枚舉時,它不能爲空,所以你的代碼從一開始就是假的。 – 2012-08-14 05:02:57

+0

@BrentArias:請參閱我的回答更新 – 2012-08-14 05:11:19

0

如何改變查詢。

 IEnumerable<ResultCode> badRule = from foo in rules 
          where !foo.Fact() && foo.Actions.Contains(actionType) 
          select foo.Code; 

和改變的ValidationResult到

public IEnumerable<ResultCode> Code; 
0

你看了這個錯誤嗎?

您的LINQ查詢返回ResultCodes的集合(IEnumerable),而不是單個ResultCode。

0

正因爲如此:

ResultCode badRule = from foo in rules 
        where !foo.Fact() && foo.Actions.Contains(actionType) 
        select foo.Code; 

返回結果代碼的集合,而您試圖將其分配到一個單一的ResultCode變量。

如果您知道只有一個結果,那麼您可以使用First選擇它並將其分配給badRule。或者FirstOrDefault如果可能有1或0個結果。