인터페이스/기본 클래스 유형 목록에 일반 목록을 캐스팅하는 방법이 있습니까?

StackOverflow https://stackoverflow.com/questions/188769

  •  06-07-2019
  •  | 
  •  

문제

나는 그들이 만든 미친 상황에서 누군가에게 인터페이스에 대한 용도를 보여 주려고 노력하고 있습니다. 목록에는 몇 가지 관련이없는 객체가 있으며 각 객체에서 두 개의 문자열 속성에서 작업을 수행해야합니다. 속성을 인터페이스의 일부로 정의하면 인터페이스 객체를 작동하는 메소드 매개 변수의 유형으로 사용할 수 있다고 지적합니다. 예를 들어:

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에서도 작동 할 수있는 메소드를 찾고있었습니다. 이것이 가능 해야하는 것 같습니다. 내가 무엇을 놓치고 있습니까?

도움이 되었습니까?

해결책

문제는 방법이 아닌 방법이 아니라 .....

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

다른 팁

실패한 이유는 제네릭이 C# (아직)에서 차이를 나타내지 않기 때문입니다.

ienumerable에 대한 수정은u003CT> 그러나 이것을 시도하십시오.

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

편집 : 다른 기존의 답변은이 특정 사례의 경우 위의 답변보다 낫지 만 실제로 시퀀스를 "변환"해야하는 경우 일반적으로 유용한 것으로 남겨 둘 것입니다.

당신은 그냥 사용할 수 있습니다 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();
}

당신이 원하는 것을 "인터페이스 공분산"이라고하며 현재 C#에 의해 지원되지 않습니다. 당신은 그것에 대해 읽을 수 있습니다 Eric Lippert의 블로그.

이것은 귀하의 질문에 대답하지 않습니다 (또는 내가 추측하는 운동의 요점 :)이 경우에만 관심의 속성에 특수 속성을 첨부하여 반사를 사용합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top