2012-11-27 1 views
0

아래 코드를 참조하십시오. 예외 "InvalidCastException"을 리턴합니다. 그리고 주요 질문은 - 왜?
무엇이 잘못 되었나요?linq의 InvalidCastException 오류

오류 텍스트 :

유형 의 개체를 캐스팅 할 수 없습니다 'WhereSelectListIterator`2는 [Monopolowy_beta.Gracz는 Monopolowy_beta.Gracz]' 은 'Monopolowy_beta.Gracz'를 입력합니다. 이 라인에서

namespace Monopolowy_beta 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Gracz> lista = new List<Gracz> { }; 
      Gracz g1 = new Gracz(); 
      Gracz g2 = new Gracz(); 
      Gracz g3 = new Gracz(); 
      g2.Id = 3; 

      lista.Add(g1); 
      lista.Add(g2); 
      lista.Add(g3); 

      g1 = GraczeTools.UstawAktywnegoGracza(lista, 3); 


      Console.ReadKey(); 
     } 
    } 
} 

오류 :
var docelowy = from item in listagraczy where (item.Id==ID && item.czyAktywny == true) select listagraczy[listagraczy.IndexOf(item) + 1]; gracz = (Gracz)docelowy;

namespace Monopolowy_beta 
{ 
    static class GraczeTools 
    { 

     public static Gracz UstawAktywnegoGracza(List<Gracz> listagraczy, int ID) 
     { 
      Gracz gracz = new Gracz(); 
      if (ID == 4){ 
       var docelowy = from item in listagraczy where (item.czyAktywny == true && item.Id == 3) select listagraczy[1]; 
       gracz = (Gracz)docelowy; 
      } 

      if (ID != 4){ 
       var docelowy = from item in listagraczy where (item.Id==ID && item.czyAktywny == true) select listagraczy[listagraczy.IndexOf(item) + 1]; 
       gracz = (Gracz)docelowy; 
      } 


      return gracz; 
     } 

    } 
} 

답변

3
var docelowy = from item in listagraczy 
       where (item.czyAktywny == true && item.Id == 3) 
       select listagraczy[1]; 

gracz = docelowy.FirstOrDefault();이의이 쿼리를 살펴 보자 사용합니다. 조건을 만족하는 모든 항목을 찾습니다 (예, 단일 항목이 아닌 시퀀스를 반환합니다). 각 항목에 대해 listagraczy 목록의 두 번째 요소를 반환합니다. 예, 귀하의 상태와 일치하는 항목이 없습니다.

나는 IEnumerable<Gracz> 결과를 반환합니다 기본의 요청에 의한 때문에, 대신 (쿼리의 범위 변수를) item를 선택하고 결과에 FirstOrDefault을 적용한다고 생각합니다. 유창 API를 사용하여 작성하는 것이 좋습니다

var docelowy = (from item in listagraczy 
       where (item.czyAktywny == true && item.Id == 3) 
       select item).FirstOrDefault(); 

:

var docelowy = listagraczy.FirstOrDefault(item => item.czyAktywny && item.Id == 3); 

은 또한 조건에 직접적으로 부울 값을 사용할 수 있습니다 (즉, item.czyAktywny 대신 item.czyAktywny == true의). 작동 원리


작은 리팩토링 후 당신의 방법은

public static Gracz UstawAktywnegoGracza(List<Gracz> listagraczy, int ID) 
{ 
    return listagraczy 
      .FirstOrDefault(item => item.Id == 3 && (ID != 4 || item.czyAktywny)); 
} 

과 같아야합니다

을 당신은 실제로 if ... else이다 (당신의 방법 if (ID == 4)if (ID != 4) 두 조건 블록이 차이가 있다는 것입니다. 첫 번째 경우에 하나 더 조건에 따라 시퀀스를 필터링하고 있습니다 (item.czyAktywny). 두 번째 경우에는이 속성이 중요하지 않으므로 하나의 필터링 조건을 추가 할 수 있습니다. d (ID != 4 || item.czyAktywny) - ID가 4 인 경우에만 czyAktywny가 확인됩니다. 또한 귀하의 메서드에 새로운 Gracz 개체를 만들 필요가 없습니다. 왜냐하면 어쨌든 통과 된 목록에서 하나를 반환하기 때문입니다.

+1

예, 대답에서 언급 한 '길 수'는 여기에서 자세히 설명되어 있으며, 한 줄짜리 문자는 내가 생각했던 것보다 더 철자가 맞습니다. +1, 좋은 물건. – tmesser

+0

어, 큰 감사 @ lazyberezovsky, 좋은 충고! ;-) – whoah

+0

하지만 마지막으로 -이 코드의 일부를 exacly 수행하는 방법을 설명해 주시겠습니까? 'item => item.Id == 3 && (ID! = 4 || item.czyAktywny)'. 나는 그 결과와 그것을 어떻게 알 수 있느냐를 잘 알고 있지만, 한 단계 한 단계를 기술 할 수 있다면 감사 할 것입니다. – whoah

1

대신 gracz = (Gracz)docelowy;의,

1

귀하의 선택 진술 문은 IEnumerable<Gracz>입니다. 따라서 이것을 Gracz으로 직접 전송하려고하면 컴퓨터가이를 수행하는 방법을 모르고보고있는 오류를 던집니다.

당신이이 상황을 처리 할 수있는 여러 가지 방법이 있지만 가장 간단한 당신 대신 당신이 현재 가지고있는의

gracz = docelowy.FirstOrDefault(); 

을 제공, 단순히 호출에 FirstOrDefault를 추가하는 것입니다. 그건 그렇고, 당신도 다른 if 진술에 이것을 추가해야합니다 - 그것은 같은 문제가 있습니다.