2016-07-07 19 views
1

Könnte mir bitte jemand erklären, warum die folgende Besetzung nicht funktioniert und die Lösung für das Problem.InvalidCastException: Unable cast generische Liste zu Objekt

Ich habe eine GroupedResult:

public class GroupedResult<TKey, TElement> 
{ 
    public TKey Key { get; set; } 

    private readonly IEnumerable<TElement> source; 

    public GroupedResult(TKey key, IEnumerable<TElement> source) 
    { 
     this.source = source; 
     this.Key = key; 
    } 
} 

public class Bacon 
{ 
} 

ich die List<string, Bacon> zu List<string, object> werfen möchte. Ich habe die folgenden und andere Möglichkeiten ausprobiert.

var list = new List<GroupedResult<string, Bacon>> 
    { 
     new GroupedResult<string, Bacon>("1", new List<Bacon>()), 
     new GroupedResult<string, Bacon>("2", new List<Bacon>()) 
    }; 

var result = list.Cast<GroupedResult<string, object>>().ToList(); 

Aber ich bekomme immer folgende Fehlermeldung:

InvalidCastException: Unable to cast object of type 'GroupedResult 2[System.String,UserQuery+Bacon]' to type 'GroupedResult 2[System.String,System.Object]'.

+4

Klassen sind unveränderlich so eine 'GropuedResult ' ist kein 'GroupedResult '. – Lee

Antwort

1

Damit das funktioniert, müssten Sie eine Schnittstelle anstelle des Klassentyps verwenden.

public interface IGroupResult<TKey, out TElement> 
{ 
    TKey Key { get; set; } 
} 

public class GroupedResult<TKey, TElement> : IGroupResult<TKey, TElement> 
{ 
    public TKey Key { get; set; } 

    private readonly IEnumerable<TElement> source; 

    public GroupedResult(TKey key, IEnumerable<TElement> source) 
    { 
     this.source = source; 
     this.Key = key; 
    } 
} 

public class Bacon 
{ 

} 

Dann könnte man so etwas wie

IGroupResult<string, Bacon> g = new GroupedResult<string, Bacon>("1", new List<Bacon>()); 

var result = (IGroupResult<string, object>)g; 

tun das, weil Kovarianz nur auf Schnittstellen und Delegierten erlaubt, aber keine Klassen. Beachten Sie, dass Sie einen Typ nur dann als Co-Variante markieren sollten, wenn er nur aus der Schnittstelle herauskommt (Methodenrückgabetyp und Nur-Lese-Eigenschaften).

Obwohl Sie sich fragen sollten, warum Sie etwas auf object zu werfen, wenn Sie mit Generika arbeiten. Der Hauptpunkt von Generika ist es, zu vermeiden, den Typ object als einen Haken alle zu verwenden, und dies könnte einen Fehler in Ihrem Design anzeigen, die Sie vielleicht überdenken möchten.

0

Es wäre besser, mit einer GroupedResult < Zeichenfolge zu starten, object> dann könnte man dies tun

new GroupedResult<string, object>("2", new List<Bacon>()) 
0

warum aren Sie verwenden GroupedResult<string, object> anstelle von GroupedResult<string, Bacon>? wie folgt:

var list = new List<GroupedResult<string, object>> 
    { 
     new GroupedResult<string, object>("1", new List<Bacon>()), 
     new GroupedResult<string, object>("2", new List<Bacon>()) 
    }; 
0

Sie können eine Cast Methode in Ihrer GroupedResult Klasse haben und sie zum Gießen verwenden!

public class GroupedResult<TKey, TElement> 
{ 
    public TKey Key { get; set; } 

    private readonly IEnumerable<TElement> source; 

    public GroupedResult(TKey key, IEnumerable<TElement> source) 
    { 
     this.source = source; 
     this.Key = key; 
    } 

    public GroupedResult<TKey, object> Cast() 
    { 
     return new GroupedResult<TKey, object>(Key, source.Cast<object>()); 
    } 
} 

public class Bacon 
{ 
} 

static void Main(string[] args) 
{ 

    var list = new List<GroupedResult<string, Bacon>> 
    { 
     new GroupedResult<string, Bacon>("1", new List<Bacon>()), 
     new GroupedResult<string, Bacon>("2", new List<Bacon>()) 
    }; 

    // var result = list.Cast<GroupedResult<string, object>>().ToList(); 
    List<GroupedResult<string,object>> result = list.Select(B => B.Cast()).ToList(); 
}