5 Stimmen

IEnumerable<T> Umwandlung

Gegeben sei das Folgende:

class Base<T> {/*...*/}
class Der<T>: Base<T> {/*...*/}

interface Sth<T>{
  IEnumerable<Base<T>> Foo {get;}
}

// and implementation...
class Impl<T>: Sth<T> {
  public IEnumerable<Base<T>> Foo {
    get {
      return new List<Der<T>>();
    }
  }
}

Wie kann ich das kompilieren? Der Fehler ist offensichtlich, nicht implizite Konvertierung von List<Der<T>> nach List<Base<T>> gefunden. Wenn ich es explizit caste, tritt InvalidCastException auf.

6voto

bcat Punkte 8676

Die Konvertierung, die Sie vorzunehmen versuchen, wird ab Version 3.5 des .NET Framework nicht mehr unterstützt. Sie wird in Version 4.0 (Visual Studio 2010) unterstützt, und zwar durch die Hinzufügung von generische Kovarianz/Kontravarianz . Damit können Sie zwar immer noch nicht werfen List<Der> a List<Base> es wird ermöglichen Ihnen die Besetzung IEnumerator<Der> (die die Liste implementiert) zu IEnumerator<Base> .

In der Zwischenzeit können Sie Ihre eigene Klasse schreiben, die Folgendes implementiert IEnumerable<Base> und gibt eine benutzerdefinierte IEnumerator<Base> die einfach umhüllt List<Der> 's IEnumerator<Der> . Wenn Sie das .NET Framework Version 3.5 verwenden, können Sie alternativ die Methode der Gussverlängerung , wie andere vorgeschlagen haben.

4voto

itowlson Punkte 72130

List<Der<T>> ist nicht konvertierbar in List<Base<T>> denn letztere können eine Base<T> hinzugefügt werden, während dies bei ersteren nicht möglich ist.

Sie können dies mit der Methode der Cast-Erweiterung beheben: return new List<Der<T>>().Cast<Base<T>>();

1voto

CRice Punkte 11793

Damit es kompiliert...

class Impl<T> : Sth<T>
{
    public IEnumerable<Base<T>> Foo
    {
        get
        {
            return new List<Base<T>>(); //change the List type to Base here
        }
    }
} 

Sie könnten auch so etwas tun, was die IEnumerable der Base-Klasse von einer Implementierung von Der zurückgeben würde

class Impl<T> : Sth<T>
{
    public IEnumerable<Base<T>> Foo
    {
        get
        {
            List<Der<T>> x = new List<Der<T>>();

            foreach (Der<T> dt in x)
            {
                yield return dt;
            }
        }
    }
}

1voto

FacticiusVir Punkte 2017

Sie können LINQ verwenden, um von List<Der<T>> zu einer IEnumerable<Base<T>>, zu verwenden:

class Impl<T>: Sth<T>
{
    public IEnumerable<Base<T>> Foo
    {
        get
        {
            return new List<Der<T>>().Cast<Base<T>>();
        }
    }
}

Wie die anderen Antworten angegeben haben, wird die generische Konvarianz in v3.5 nicht unterstützt, aber Sie können LINQ verwenden, um ein Wrapper-Objekt zu erstellen, das IEnumerable<Base<T>>.

0voto

ken Punkte 16622

Diese Antworten haben mir geholfen, und ich wollte nur meine Lösung für ein ähnliches Problem posten, das ich hatte.

Ich habe eine Erweiterungsmethode für IEnumerable geschrieben, die automatisch TSource castet, wenn ich eine List<Foo> in eine IEnumerable<Bar> umwandeln will (ich bin noch auf 3.5).

public static SpecStatus Evaluate<TSource, TSpecSource>(this IEnumerable<TSource> source, ISpec<IEnumerable<TSpecSource>> spec)
        where TSource : TSpecSource
{
    return spec.Evaluate(source.Cast<TSpecSource>());
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X