2011-01-25 2 views
2

이러한 유형의 사용 : 예상Enumerable.Cast <>에서 변환 연산자를 사용하지 않는 이유는 무엇입니까?

var ok=test.Select(x => (int)x).ToList(); 

class Foo 
{ 
    public static implicit operator int(Foo obj) 
    { 
    return 5; 
    } 
} 

var test=new[] { new Foo() }; 

다음 작품을하지만> InvalidCastException이 실패 < 캐스트 사용 - 왜?

var fail=test.Cast<int>().ToList(); 
+1

이것이 문제인 경우 다음을 참조하십시오. http://stackoverflow.com/questions/445471/puzzling-enumerable-cast-invalidcastexception/445497#445497 –

+0

나는 이것을 시도했지만 코드 예제가 전혀 작동하지 않았으므로 okd InvalidCastException이있는 행,이 예제가 제대로 작동하는지 확인 하시겠습니까? –

+0

@matt - 예, 링크 해 주셔서 감사합니다! 전에는 그것을 보지 못했습니다. – laktak

답변

2

Linq (EduLinq)를 다시 구현하는 것에 대한 Jon Skeet의 블로그, 특히 part 33을 읽습니다.

캐스트 (.NET 3.5 SP1 기준) 캐스트 및 OfType은 참조 및 언 박싱 전환 만 수행합니다. boxed int를 long으로 변환하거나 사용자 정의 변환을 실행하지 않습니다. 기본적으로 객체에서 일반 유형 매개 변수로 변환하는 것과 동일한 규칙을 따릅니다. (구현하기에 매우 편리합니다!)

0

Enumerable.Cast에 대한 설명서는 사실 모호하고 전송 및 변환에 대해 이야기하고 있습니다. 그러나 "요소가 TResult를 입력 할 수없는 경우이 메서드는 예외를 throw합니다."클래스 Foo는 int로 캐스트 할 수 없지만 캐스트 구문을 사용하여 변환 할 수 있다고 말합니다. 후자는 메서드 호출입니다.

보통 캐스트와 '일'로 'OfType 유사한 일을하고 당신이 쓴 경우 :

var foo = new Foo() 
var bar = foo is int; 

줄이 잘못된 것입니다. 캐스트가 일관성이있는 것처럼 보일 것입니다 (MSDN에있는 설명서는 전적으로 아닙니다). is-operator가 false를 반환하면 실패합니다. (시퀀스의 값이 null이고 T가 참조 유형 인 경우 특별한 경우가 하나 있습니다.)

1

캐스팅 연산자는 순전히 C# 컴파일러 수준의 기능이므로 런타임에 대해서는 아무 것도 알지 못하므로 일반적인 캐스트 메서드를 통해이를 구현하는 간단한 방법이 없습니다. 이렇게하는 한 가지 방법은 런타임 코드 생성을 수행하는 것입니다

 

    public static class Converter<TSource, TResult> 
    { 
     static Converter() 
     { 
      var sourceParameter = Expression.Parameter(typeof(TSource)); 
      var conversionExpression = Expression.Lambda<Func<TSource, TResult>>(
       Expression.Convert(sourceParameter, typeof(TResult)), 
       sourceParameter); 

      Instance = conversionExpression.Compile(); 
     } 

     public static Func<TSource, TResult> Instance 
     { 
      get; 
      private set; 
     } 
    } 

    public static class EnumerableEx 
    { 
     public static IEnumerable<TResult> Cast<TSource, TResult>(this IEnumerable<TSource> source) 
     { 
      return source.Select(Converter<TSource, TResult>.Instance); 
     } 
    } 
 

을하지만 당신은 검사 컴파일 시간을 풀 수 있습니다 :

 

var test = new[] { new Foo() }; 
var ok = test.Cast<Foo, int>().ToList(); // compiles and works ok 
var error = test.Cast<Foo, double>().ToList(); // compiles but fails at run-time 
 

또 다른 방법은 Puzzling Enumerable.Cast InvalidCastException 그러나이 같이 반사를 사용하는 것입니다 int에서 long 같은 기본 제공 전환에서는 작동하지 않습니다.

관련 문제