2014-01-14 71 views
4

我有一個方法是返回一個列表的List<KeyValuePair<int,string>>;然而,我發現了一個錯誤:無法將源類型轉換爲目標類型List <KeyValuePair> Linq

Cannot convert source type System.Collections.Generic.List<{Key:int, Value:string}> to target type System.Collections.Generic.KeyValuePair<'int,string'>> .

我試圖做一個LINQ的select語句到一個新的列表,但我不明白,如果初始化列表是問題,或者它如何我越來越Linq語句中的值。

這裏是方法:

public static List<KeyValuePair<int,string>> GetStatus(int status) 
{ 
    List<KeyValuePair<int,string>> st = SelectList.GetStatuses(); 
    List<KeyValuePair<int,string>> tp; 

    switch(status) 
    { 
     case (int)Status.Completed: 
      tp = st.Where(s => s.Key == (int)Status.Completed || 
          s.Key == (int)Status.NotValid) 
       .Select(s => new { s.Key, s.Value }).ToList(); 
     case (int)Status.Open: 
      tp = st.Where(s => s.Key == (int)Status.Open || 
          s.Key == (int)Status.Reviewed) 
       .Select(s => new { s.Key, s.Value }).ToList(); 
     default: 
      break; 
    } 
    return tp; 
} 

下面是填充列表的方法:

public static List<KeyValuePair<int, string>> GetStatuses() 
    { 
     using (var con = new SqlConnection()) 
     { 
      var sql = @"SELECT ID [Key], Text [Value] from Statuses"; 

      return (con.Query<KeyValuePair<int, string>>(sql.ToString(), commandType: commandType:Text) ?? Enumerable.Empty<KeyValuePair<int, string>>()).ToList(); 
     } 
    } 

回答

5

當你寫new { s.Key, s.Value }你實例化一個新的匿名類型與性質KeyValue。相反,您可能打算通過編寫new KeyValuePair(s.Key, s.Value)來使用KeyValuePair的構造函數。

也請注意,您的Where子句已經過濾了KeyValuePairs的列表,因此不需要進行任何投影。換句話說,在這種情況下,您可以刪除整個Select聲明。

所以,你可以使用KeyValuePair構造函數和寫:

tp = st.Where(s => s.Key == (int)Status.Open || s.Key == (int)Status.Reviewed) 
     .Select(kvp => new KeyValuePair(kvp.Key, kvp.Value)).ToList(); 

,或者甚至更好,簡單地丟棄Select聲明:

tp = st.Where(s => s.Key == (int)Status.Open || s.Key == (int)Status.Reviewed).ToList(); 

多一點點的匿名類型:匿名類型是一種C#功能,可讓您使用自定義屬性創建快速臨時類。它們對Linq查詢尤其有用。當您的程序編譯時,會發出一個新的匿名類型,其中包含名爲KeyValue的兩個屬性。你可以看到這個新類沒有名字,只有2個屬性(全類和匿名類之間還有一些不同之處,但這是考慮它的一種便利方式)。您的方法預計會返回KeyValuePairs的列表,但您已提供了此新類型的對象列表。詳細瞭解它們here

作爲一般的小調,你根本不需要聲明tp變量。相反,您可以在switch聲明中輸入return

+2

他的返回類型是一個列表,所以ToList是必要的btw –

+0

@JustinPihony謝謝,編輯。 –

+0

我不知道我可以完全刪除選擇部分,但這當然確實使它有效且易於閱讀。謝謝Ben,Sergey,Justin! –

2

不能將匿名對象列表{ Key, Value }分配給類型爲KeyValuePair<int,string>的變量。如果您想重複使用與GetStatuses()返回的相同KeyValuePair實例,則只需刪除Select投影。否則,項目中的每個鍵值對KeyValuePair<int,string>類型的新實例(下文取消註釋行):

switch(status) 
{ 
    case (int)Status.Completed: 
     tp = st.Where(s => s.Key == (int)Status.Completed || s.Key == (int)Status.NotValid) 
       //.Select(s => new KeyValuePair<int, string>(s.Key, s.Value)) 
       .ToList(); 
     break; // also make sure you have break here 
    case (int)Status.Open: 
      tp = st.Where(s => s.Key == (int)Status.Open || s.Key == (int)Status.Reviewed) 
       //.Select(s => new KeyValuePair<int, string>(s.Key, s.Value)) 
       .ToList(); 
     break; 
} 
4

正如其他人已經指出的那樣,你在你的Select,不是KeyValuePair創建一個新的匿名類型。但是,你已經工作了針對KeyValuePair,所以你甚至都不需要Select

tp = st.Where(...where...).ToList(); 

實在是沒有點重新實例在Select的對象(除非你想有一個新的參考...但在這種情況下KVP是不可變的)。 Where.ToList更具表現力,因爲它少了groh,至少恕我直言

相關問題