문제

나는 최근에 목록에 부가 (ienumerable)를 추가하려고 할 때 문제가 발생합니다. 아마도 고전적인 문제 일 것입니다. 그러나 나는 아직 그것을 얻지 못합니다.

목록 매개 변수를 기대하는 메소드는 목록에 만족하지 않는다는 것을 이해합니다. 왜냐하면 목록에 기본을 추가하려고 시도 할 수 있기 때문입니다.

그러나 Ienumerables 자체를 변경할 수 없으므로이 경우 올바르게 얻을 수 있으므로이 경우 작동해야합니다.

내가 생각한 코드는 다음과 같이 보입니다.

class Foo
{
}

class Bar : Foo
{
}

class FooCol
{
    private List<Foo> m_Foos = new List<Foo> ();

    public void AddRange1(IEnumerable<Foo> foos)
    {
        m_Foos.AddRange (foos); // does work
    }

    public void AddRange2<T>(IEnumerable<T> foos) where T : Foo
    {
        m_Foos.AddRange (foos); // does not work
    }
}

class Program
{
    static void Main(string[] args)
    {
        FooCol fooCol = new FooCol ();

        List<Foo> foos = new List<Foo> ();
        List<Bar> bars = new List<Bar> ();

        fooCol.AddRange1 (foos); // does work
        fooCol.AddRange1 (bars); // does not work

        fooCol.AddRange2 (foos); // does work
        fooCol.AddRange2 (bars); // does work
    }
}

AddRange2 메소드에서 컴파일러에 힌트를 전달하려고했지만 이것은 문제로 이동했습니다.

내 사고 방식은 결함이 있습니까? 이것은 언어의 한계입니까, 아니면 디자인에 의한 것입니까?

IIRC, 이러한 종류의 작업에 대한 지원은 Java 1.5에 추가되었으므로 향후 어느 시점에서도 C#에 추가 될 것입니다 ...?

도움이 되었습니까?

해결책

이것은 공분산이며 C# 4.0 / .NET 4.0에 고정됩니다. 지금은 일반 옵션이 최고의 답변입니다 ( IEnumerable<T> - ~ 아니다 IList<T>).

그러나 일반적인 방법 내에서, 당신은 T. 당신은 또한 사용할 수 있습니다 Cast<T> 또는 OfType<T> 비슷한 것을 달성하기 위해 LINQ와 함께.

다른 팁

C# 3.0에서는 "캐스트"확장 방법을 사용할 수 있습니다. System.linq를 가져 오면이 코드를 사용하는 경우 :

public void AddRange2<T>(IEnumerable<T> foos) where T : Foo
{
    m_Foos.AddRange (foos.Cast<Foo>());
}

그러면 그것은 당신을 위해 작동해야합니다.

확장 방법이있는 해결 방법이 있습니다.

public static IEnumerable<TBase> ToBaseEnumerable<TBase, TDerived>( this IEnumerable<TDerived> items ) where TDerived : TBase {
    foreach( var item in items ) {
        yield return item;
    }
}
...
IEnumerable<Employee> employees = GetEmployees(); //Emplyoee derives from Person
DoSomethingWithPersons( employees.ToBaseEnumerable<Person, Employee>() );

하지만 "u003CPerson, Employee> "조금 어색하다 :/.

물론 캐스트 솔루션은 클래스 캐스트 예외를 생성 할 수 있습니다. 열거 가능한 확장을 게시 한 사람은 그것이 어색하다고 말했다. 나는 어색한 절반에 불과한 솔루션을 생각해 냈습니다.

public static class UpTo<T>
{
    public static IEnumerable<T> From<F>(IEnumerable<F> source) where F:T
    {
        // this cast is guaranteed to work
        return source.Select(f => (T) f);
    }
}

용법:

ienumerable 포유류 = up tou003CMammal> .from (Kennel.Dogs)

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