Diskuze: Přetypování kolekce na typ předka
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 9 zpráv z 9.
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
To nemůžeš udělat kvůli typové varianci. Řekněme, že máš následující typy:
class BasicInfo {}
class AccidentInfo : BasicInfo {}
class AdditionalInfo : BasicInfo {}
List<BasicInfo> basics;
List<AccidentInfo> accidents;
Pokud bys přetypoval List<AccidentInfo> na List<BasicInfo>, mohl bys do něj vložit typ AdditionalInfo, jenže ten nedědí od AccidentInfo, ale pouze od BasicInfo.
Takže List<T> je invariantní a podobné přetypování je zakázané. Musíš to řešit přes generika:
void Add<T>(List<T> list, T item) where T : BasicInfo
{
list.add(item);
}
Zkusil jsem to předělat na generiku:
private List<T> AddEventClassTextAndIcon<T>(List<T> basicInfoes) where T:BasicInfo
{
T temp;
for (int i = 0; i < basicInfoes.Count; i++)
{
temp = basicInfoes[i];
temp.EventClassText = updateClassesText[temp.EventClassId - 1];
switch (temp.EventClassId)
{
//todo
}
}
return basicInfoes;
}
a tohle projde:
AddEventClassTextAndIcon<AccidentInfo>(new List<AccidentInfo>());
ale když tam pošlu List z IEnumerable tak to nefunguje:
AddEventClassTextAndIcon<AccidentInfo>(query.ToList());
No protože musíš opět dodržet typovou varianci. Máš tam bordel v typech. Stačí, když využiješ varianci:
AddEventClassTextAndIcon(new List<AccidentInfo>());
IEnumerable<BasicInfo> query = ...;
AddEventClassTextAndIcon(query.ToList());
A pokud napíšeš tu svoji metodu korektně přes IEnumerable<T> místo List<T>, nemusíš dokonce ani volat metodu ToList().
No to IEnumerable vrací AccidenInfo a ToList() volám abych odpálil dotaz do db.
var query = db.Database.SqlQuery<AccidentInfo>(sqlQueriesForAccidents[0], date.Date);
return AddEventClassTextAndIcon<AccidentInfo>(query.ToList());
Protože tam máš bordel v typech, už jsem ti to psal. Alespoň si přečti, jakou chybu píše kompilátor.
Tohle je plně funkční kód:
class Program
{
static void Main(string[] args)
{
IEnumerable<B> b = new B[10];
List<B> result = Add(b.ToList(), new B());
}
static List<T> Add<T>(List<T> list, T item) where T : A
{
list.Add(item);
return list;
}
}
class A
{
}
class B : A
{
}
Já to prostě nevidím a kompilátor píše pořád to stejné jako na začátku.
Cannot implicitly convert type 'System.Collections.Generic.List<DopDat.Models.AccidentInfo>' to 'System.Collections.Generic.List<DopDat.Models.BasicInfo>'
edit:
Ok, už to mám, jsem debil.
Děkuji za pomoc
V tom případě
hádám, že chyba bude tady: return
AddEventClassTextAndIcon<AccidentInfo>(query.ToList());
Neboli se snažíš vracet instanci typu List<AccidentInfo> a návratová hodnota je typu List<BasicInfo>.
Přesně tak, nedošlo mi, že ten error se vztahuje k tomu return, pořad
jsem si myslel, že je problém na vstupu té metody.
Zobrazeno 9 zpráv z 9.