2008-10-09 3 views
3

나는 그들이 만든 미친 상황에서 누군가 인터페이스를 사용하려고 노력하고 있습니다. 그들은 목록에 관련이없는 여러 개의 객체가 있고 각 객체의 두 문자열 속성에 대한 연산을 수행해야합니다. 인터페이스의 일부로 프로퍼티를 정의하면 인터페이스 객체를 메서드 매개 변수의 유형으로 사용할 수 있습니다. 예를 들면 :일반 목록을 인터페이스/기본 클래스 유형 목록에 전송할 수 있습니까?

void PrintProperties(IEnumerable<ISpecialProperties> list) 
{ 
    foreach (var item in list) 
    { 
     Console.WriteLine("{0} {1}", item.Prop1, item.Prop2); 
    } 
}

은 모든 좋은처럼이 보이지만에서 일해야하는 목록은 아니다 (그리고 안) 유형의 매개 변수로 인터페이스를 선언. 그러나 다른 유형 매개 변수로 형변환 할 수있는 것처럼 보이지는 않습니다. 예를 들어,이 실패하고 이유를 이해할 수 없다 :

using System; 
using System.Collections.Generic; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Test> myList = new List<Test>(); 
      for (int i = 0; i < 5; i++) 
      { 
       myList.Add(new Test()); 
      } 

      PrintList((IEnumerable<IDoSomething>)myList); 
     } 

     static void PrintList(IEnumerable<IDoSomething> list) 
     { 
      foreach (IDoSomething item in list) 
      { 
       item.DoSomething(); 
      } 
     } 
    } 

    interface IDoSomething 
    { 
     void DoSomething(); 
    } 

    public class Test : IDoSomething 
    { 
     public void DoSomething() 
     { 
      Console.WriteLine("Test did it!"); 
     } 
    } 
}

내가 이 작업을 수행 할 Enumerable.Cast<T> 멤버를 사용할 수 있지만, 나뿐만 아니라 .NET 2.0에서 작업 할 수있는 방법을 찾고 있었다. 이것이 가능해야하는 것처럼 보입니다. 나는 무엇을 놓치고 있습니까?

답변

5

문제는 제네릭은 C#을 (아직)에 차이를 나타내지 않기 때문에 실패 이유는

void PrintProperties<SP>(IEnumerable<SP> list) where SP: ISpecialProperties 
{ 
    foreach (var item in list) 
    { 
     Console.WriteLine("{0} {1}", item.Prop1, item.Prop2); 
    } 
} 
+0

정확히 내가 작성한 것. –

+0

나는 그것을 가로 질러 넘어졌고, 그것을 게시하려고오고 있었다. 이상하게 들릴 지 모르지만이 방법이 왜 그런지 이해할 수 있습니다. 유형을 캐스팅 할 수 있도록 지정해야합니다. – OwenP

5

.....없는이 호출 방법과 함께 방법입니다. 다른 기존 응답이 특정 사건에 대한 위보다 더 나은,하지만 난 여기에이 떠날거야 :

public static IEnumerable<TBase> SafeConvert<TBase, TDerived>(IEnumerable<TDerived> source) 
    where TDerived : TBase 
{ 
    foreach (TDerived element in source) 
    { 
     yield return element; // Implicit conversion to TBase 
    } 
} 

편집 :

를 IEnumerable < T>에 대한 수정에 관해서는, 그러나,이 시도 실제로 시퀀스를 "변환"해야하는 경우 일반적으로 유용합니다.

+0

Ah Skeet 씨 - 저에게 막대한 도움을 준 훌륭한 사례입니다, 감사합니다! – BenAlabaster

1

당신은 가지고있는 목록에 foreach을 사용할 수 있습니다. foreach은 캐스트가 내장되어 있습니다. 당신이 함수에서 루프를 가지고가는 경우에 그래서 당신이 당신의 질문 (또는 내가 :) 추측 운동의 포인트를 응답하지 않습니다

List<Test> myList = new List<Test>(); 
for (int i = 0; i < 5; i++) 
{ 
    myList.Add(new Test()); 
} 

foreach (IDoSomething item in myList) 
{ 
    item.DoSomething(); 
} 
+0

주목할 가치가있는 것은 (foreach에서는 캐스트입니다.)하지만, 함수가 다른 일을해야하는 경우 여러 파생 된 형식의 목록을 같은 함수에 전달하는 문제를 해결하지 못합니다. –

-1

같은 것을 쓸 수 있지만, 난 그냥이의 반사를 사용하십시오 특별한 속성을 관심있는 속성에 첨부하여

+0

Yikes! 그것은 느리고 복잡합니다. 차라리 내 친구에게 유형에 따라 코드를 복제하도록 말하고 싶습니다. – OwenP

1

"인터페이스 공분산"이라고하는 것이 현재 C#에서 지원되지 않습니다. Eric Lippert's blog에 대한 내용을 읽을 수 있습니다.