2014-01-14 1 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를 선택 성명을 발표하려고하지만 난 이해가 안 나 : 그러나, 나는 오류를 받고 있어요 Linq 문에있는 값 당신은 당신이 속성 KeyValue으로 새 익명 형식을 인스턴스화하는 new { s.Key, s.Value }을 쓸 때

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

:

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; 
} 

는 여기에 목록을 채우는 방법이다 : 여기

는 방법이다. 대신, 아마도 KeyValuePair의 생성자를 사용하여 new KeyValuePair(s.Key, s.Value)을 작성해야합니다.

귀하의 Where 절이 이미 KeyValuePairs의 목록을 필터링하고 있기 때문에 투영도 필요하지 않습니다. 즉,이 경우 전체 Select 문을 삭제할 수 있습니다. 익명 형식에 조금 더

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

: 더 나은, 단순히 Select 문을 드롭

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

을 또는 :

그래서, 당신은 KeyValuePair 생성자를 사용할 수 및 쓰기 익명 유형을 사용자 지정 속성을 사용하여 빠른 임시 클래스를 만들 수있는 C# 기능입니다. 특히 Linq 개의 검색어에 유용합니다. 프로그램이 컴파일되면 KeyValue이라는 2 개의 속성으로 새로운 익명 형식이 생성됩니다. 이름없는이 새로운 클래스는 정확히 2 개의 속성을 포함 할 수 있습니다 (본격적인 클래스와 익명 형식 사이에는 몇 가지 다른 차이점이 있지만 생각할 수있는 편리한 방법입니다). 메서드가 KeyValuePairs의 목록을 반환 할 것으로 예상되지만이 새 유형의 개체 목록을 제공했습니다. 그들에 대한 자세한 내용은 here을 참조하십시오.

일반적인 사소한 메모로 tp 변수를 전혀 선언 할 필요가 없습니다. 대신 switch 명세서에 return 문을 쓸 수 있습니다.

+2

그의 반환 유형은 List이므로 ToList가 필요합니다. btw –

+0

@JustinPihony 감사합니다. –

+0

내가 선택한 부분을 완전히 삭제할 수 있다는 것을 알지 못했지만 확실히 효율적으로 읽고 쉽게 읽을 수 있습니다. 감사합니다 벤, 세르게이, 저스틴! –

2

KeyValuePair<int,string> 유형의 변수에 익명 개체 목록 { Key, Value }을 할당 할 수 없습니다. 동일한 KeyValuePair 인스턴스를 다시 사용하여 GetStatuses() 전화를 걸고 싶다면 Select 투영을 제거하면됩니다. 다른 사람이 이미 지적했듯이

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<int,string> 유형의 새로운 인스턴스에 각 키 값 쌍 (아래 주석 라인)을 전망이다.그러나, 당신은 이미 KeyValuePair에 대해 작업하는, 그래서 당신은 심지어 새 참조를하지 않으합니다 (Select의 개체를-인스턴스 다시 할 점은 정말이없는 Select

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

필요하지 않습니다 ...하지만 KVP는이 경우 변경할 수 없음). Where.ToList은 grok에 덜 적기 때문에 더 표현력이 뛰어납니다. 적어도 IMHO

관련 문제