2009-05-23 3 views
22
이것은 내 함수입니다 : "myLine"IEnumerable [string]이 아니고 IEnumerable [Anonymous]를 작성하는 방법을 모르므로 컴파일 오류가 발생합니다. "암시 적으로 변환 할 수 없습니다. 'System.Collections.Generic.IEnumerable [AnonymousType # 1]'을 'System.Collections.Generic.IEnumerable [string]'으로 변환하십시오. ""

답변

15

당신은 IEnumerable<AnonymousType>를 선언 할 수 없습니다 유형이 빌드시에는 (알려진) 이름이 없기 때문입니다. 따라서이 유형을 함수 선언에서 사용하려면 일반 유형으로 만드십시오. 또는 검색어를 수정하여 IENumerable<String>을 반환하고 해당 유형을 고수하십시오.

다음 문의를 사용하여 IEnumerable<KeyValuePair<Int32, String>>을 반환하십시오.

select new KeyValuePair<Int32, String>(id, m.Groups[2].Value) 
+2

"select new {...}"라고 말하면 AnonymousType을 만들었습니다. –

+0

아니요하지만 IEnumerable을 반환하고 CastByExample 트릭을 사용할 수 있습니다 . –

0

한 가지 LINQdeferred execution을 사용하는 것입니다 " 'System.Collections.Generic.IEnumerable [문자열]에 유형'System.Collections.Generic.IEnumerable [1 AnonymousType 번호]를 '변환합니다. 즉, foreach 문을 반복하거나 메서드를 myLine에 호출 할 때까지 LINQ 문이 실제로 실행되지 않습니다. 귀하의 예를 들어
은 변경 시도 :

return myLine; 

에 :

return myLine.ToList(); 
+0

문제는 프로 시저 정의에 도움, 그래서 "개인 목록 SeachItem (INT [] ItemIds)"해야하지만, 그 중 하나가 작동하지 않습니다. "암시 적으로 형식을 변환 할 수 없습니다 : [AnoynymousType # 1]을 List [string]에 나열하십시오. 그냥 할 수 없다면 알려주세요. :) –

8

SearchItem에 메소드 서명은 메소드가 IEnumerable<string> 반환하지만 LINQ 쿼리에 선언 된 익명 형식 유형 string이 아닌 것을 나타냅니다. 동일한 메소드 서명을 유지하려면 string만을 선택하도록 쿼리를 변경해야합니다. 예 : 당신이 당신의 쿼리에 의해 선택된 데이터를 반환 주장하는 경우

return myLine.Cast<object>(); 

return 문을 교체 할 경우

return myLine.Select(a => a.Text); 

, 당신은 그럼 당신은 반사를 사용하여 객체를 소비 할 수있는 IEnumerable<object>을 반환 할 수 있습니다.

그러나 실제로, 선언 된 메서드 외부에서 익명 형식을 사용하려는 경우 메서드가 해당 클래스의 IEnumerable을 반환하도록 클래스를 정의해야합니다. 익명 유형은 편리하지만 악용 될 수 있습니다.

5

귀하의 기능은 사용자가 실행하고있는 LINQ 문이 실제로 T는 컴파일시 생성 된 형식 인 IEnumerable을 <T>을 반환하는 경우, IEnumerable을 < 문자열 >을 반환하도록 노력하고있다. 익명 형식은 코드가 컴파일 된 후에 특정 형식을 취하기 때문에 항상 익명이 아닙니다.

그러나 익명 형식은 컴파일 될 때까지 일시적이므로 익명 형식은 만든 범위에서만 사용할 수 있습니다.당신의 궁극적 인 목표는 어떤 종류를 검색 할 수없는 경우,

public class SearchItemResult 
{ 
    public string Text { get; set; } 
    public int ItemId { get; set; } 
    public string Path { get; set; } 
} 

public IEnumerable<SearchItemResult> SearchItem(int[] itemIds) 
{ 
    // ... 
    IEnumerable<SearchItemResult> results = from ... select new SearchItemResult { ... } 
} 

그러나 : 사용자가 제공 한 예에서 사용자의 요구를 지원하기 위해, 나는 간단한 해결책이 쿼리의 결과를 저장하는 간단한 개체를 만드는 것입니다 말할 것

IEnumerable<string> lines = from ... select m.Groups[2].Value; 

내가 그 LINQ, enumerables, 그리고 익명의 유형에 대한 이해를 명확히 도움이되기를 바랍니다 : 객체, 당신은 경로, 말, 만 관심이 있습니다 ... 당신은 여전히 ​​IEnumerable을 < 문자열 >를 생성 할 수 있습니다. :) 내가 반드시이 추천하고 있지 않다

+1

FYI : 익명 형식이 생성되는 범위에서 고유하다고 말하는 것은 정확하지 않습니다. 익명 형식은 구조적으로 같은 ssembly는 두 가지 다른 메소드에서 실제로 사용되지만 그 메소드간에 공유됩니다. 이 사실을 활용할 수있는 영리한 방법이 있지만 권장하지는 않습니다. 두 가지 방법을 통해 유형을 공유해야하는 경우이를 공칭으로 만듭니다. –

+0

Microsoft의 Eric Lippert가 유명인입니까? 가방을 열었 으면 고양이를 내보내 야합니다. 범위에서 익명 형식을 어떻게 공유합니까? ;) – jrista

+1

매우 조심스럽게. 구피 방식의 추론 트릭과 캡처 된 외부 변수를 사용해야합니다. 어쩌면 나는 그 시간에 블로그를 할 것입니다. –

6

... 이 타입 시스템의 전복의 일종이다 그러나 당신이 할 수있는 :)

1 IEnumerable (비 일반적인 하나를 반환하도록 메서드 서명을 변경

0 :

public static class Extensions{ 
    public static IEnumerable<T> CastByExample<T>(
      this IEnumerable sequence, 
      T example) where T: class 
    { 
     foreach (Object o in sequence) 
      yield return o as T; 
    } 
} 

3) 다음과 같은 방법 뭔가를 호출)

2

)를 cast by example 도우미를 추가

그리고 끝났습니다.

이 키는 동일한 순서, 유형 및 속성 이름을 가진 두 개의 장소에서 익명 유형을 만드는 경우 유형이 재사용된다는 사실입니다. 이것을 알면 제네릭을 사용하여 반사를 피할 수 있습니다.

희망이 알렉스

+0

Clever. 그러나 정말로, 누군가가 그렇게 많은 문제를 겪게된다면, 선언 된 클래스에 데이터를 캡슐화해야합니다. – jason

+2

내가 말했듯이, 나는 이것을 추천하지 않고있다;) –

+0

... 흥미롭게도이 문제는 한 번만, 즉 헬퍼 확장 방법을 사용하면 다시 사용하기가 쉽다. 어디에서나 새로운 유형의 롤링과는 다릅니다. 어쨌든 이것은 .NET 4.0에서 Tuple 의 작업입니다 –

관련 문제