그것은 잘못을 캐스팅하려면 열거자 아이의 등을 열거자의 부모 등?

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

  •  04-07-2019
  •  | 
  •  

문제

나에 오류가 나를 구축합니다:

오류 12 할 수 없는 암시적으로 변환 유형 '시스템이다.컬렉션이 있습니다.일반적입니다.IEnumerator<공공 무>' 하기 '시스템이다.컬렉션이 있습니다.일반적입니다.IEnumerator< IParentClass>'.는 명시적 변환 존재하는(당신은 당신 누락 캐스팅?)

그것은 잘못을 단순히 발리?

이것은 나의 코드:

public Dictionary<Int32, BaseClass> Map { get; private set; }

public IEnumerator<BaseClass> GetEnumerator()
        {
            return this.Map.Values.GetEnumerator();
        }

public IEnumerator<IParentClass> IEnumerable<IParentClass>.GetEnumerator()
        {
            return this.GetEnumerator(); // ERROR!
        }

나의 질문은,나는 그냥 변경이 라인:

return this.GetEnumerator();

하기:

return (IEnumerator<IParentClass>)this.GetEnumerator();

(지 않고 어떤 나쁜 부작용)?

접수 응답:
내가 변했어요 기능은 다음(을 읽은 후에 존 스키트의 게시물):

IEnumerator<IParentClass> IEnumerable<IParentClass>.GetEnumerator()
        {
            return this.Map.Values.Cast<IParentClass>().GetEnumerator();
        }
도움이 되었습니까?

해결책

현재 C#에서 제네릭이 공분산이 아니기 때문에 할 수 없습니다. .NET 자체에는 약간의 지원이 있지만 (대표 및 인터페이스의 경우) 아직 사용되지 않았습니다.

당신이 돌아왔다면 IEnumerable<BaseClass> 대신에 IEnumerator<BaseClass> (및 .NET 3.5를 가정) 사용할 수 있습니다 Enumerable.Cast -하지만 현재 자신의 확장 방법을 작성해야합니다.

public static IEnumerator<TParent> Upcast<TParent, TChild>
    (this IEnumerator<TChild> source)
    where TChild : TParent
{
    while (source.MoveNext())
    {
        yield return source.Current;
    }
}

또는 귀하의 경우에 귀하는 이전에 캐스트를 사용할 수 있습니다.

return this.Map.Values.Cast<BaseClass>().GetEnumerator();

다른 팁

아니요, 최소한 C# 3.0 이하의 인터페이스 분산은 지원되지 않습니다. Eric Lippert의 우수한 시리즈, 특히, 특히 이 하나.

아니요, 안전하지 않습니다. 아래를 참조하십시오.

System.collections.generic 사용; 클래스 foo {} 클래스 바 : foo {}

static class Program
{
    static IEnumerator<Foo> GetBase() {
        yield return new Foo();
        yield return new Bar();
    }
    static IEnumerator<Bar> GetDerived()
    {
        return (IEnumerator<Bar>)GetBase();
    }
    static void Main()
    {
        var obj = GetDerived(); // EXCEPTION
    }
}

그러나 반복자 블록을 사용하여 캐스트를 수행 할 수 있어야합니까?

static IEnumerator<Bar> GetDerived()
{
    using (IEnumerator<Foo> e = GetBase())
    {
        while (e.MoveNext())
        {
            // or use "as" and only return valid data
            yield return (Bar)e.Current;
        }
    }
}

하는 이유 이에 적합하지 않은,그림이 대신 Enumerator, 이, List.모두 사용하여 제네릭-컴파일러가 처리하지 않거나 특별한 방법에 관한 일반적인 인수입니다.

void doStuff() {
    List<IParentThing> list = getList();
    list.add(new ChildThing2());
}

List<IParentThing> getList() {
    return new List<ChildThing1>();  //ERROR!
}

이 첫번째 방법은 고급 목록 IParentThings 해야 할 수 있을받을 ChildThing2.하지만 목록 ChildThing1s 을 처리할 수 없습니다 ChildThing2, 또는 실제로 어떤 구현자의 IParentThingChildThing1 -즉,는 경우 List&lt;ChildThing1> 되었으로 캐스팅 List&lt;IParent>, 그할 수 있어야를 다루 모든IParentThing, 지 IParentThingChildThing1.

참고하는 자바 generics 있는 방법을 말하는"나는 아무것도의 목록에서 상속되는"이 외에도"내가 목록을 원하는 것 이 상속,"할 수있는 더 많은 흥미로(그리고 내 생각에는 우아한)솔루션은 좀 문제가 발생합니다.

IEnumerator<BaseClass> 그리고 IEnumerator<ParentClass> 관련이없는 일반적인 매개 변수는 관련이 없습니다. 대신 LINQ를 사용하겠습니다 Select 그렇게와 같은 확장 방법 :

return this.Select(x => (IParentClass)x).GetEnumerator();

아니면 그 Cast 확장 방법 :

return this.Cast<IParentClass>().GetEnumerator();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top