Diskuze: Přetypování kolekce na typ předka

C# .NET .NET (C# a Visual Basic) Přetypování kolekce na typ předka American English version English version

Avatar
g1ml1
Člen
Avatar
g1ml1:

Zdravím,
mám dvě třídy

class BasicInfo
class AccidentInfo:BasicInfo

takže můžu udělat:

BasicInfo bInfo;
AccidentInfo aInfo = new AccidentInfo();
bInfo = aInfo;

ale potřeboval bych udělat:

List<BasicInfo> basicInfoes;
List<AccidentInfo> accidentInfoes = new List<AccidentInfo>();
basicInfoes = (List<BasicInfo>)accidentInfoes;

Chtěl bych totiž použít metodu, která je napsaná pro List<BasicInfo> i pro List<AccidentInfo> (mění se jen společné property)

Editováno 3.1.2014 19:26
 
Odpovědět 3.1.2014 19:26
Avatar
coells
Redaktor
Avatar
Odpovídá na g1ml1
coells:

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);
}
 
Nahoru Odpovědět 3.1.2014 19:43
Avatar
g1ml1
Člen
Avatar
Odpovídá na coells
g1ml1:

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());
Editováno 3.1.2014 20:25
 
Nahoru Odpovědět 3.1.2014 20:24
Avatar
coells
Redaktor
Avatar
Odpovídá na g1ml1
coells:

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().

 
Nahoru Odpovědět 3.1.2014 20:32
Avatar
g1ml1
Člen
Avatar
Odpovídá na coells
g1ml1:

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());
 
Nahoru Odpovědět 3.1.2014 20:49
Avatar
coells
Redaktor
Avatar
Odpovídá na g1ml1
coells:

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
{
}
 
Nahoru Odpovědět 3.1.2014 20:57
Avatar
g1ml1
Člen
Avatar
Odpovídá na coells
g1ml1:

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

Editováno 3.1.2014 21:15
 
Nahoru Odpovědět 3.1.2014 21:11
Avatar
coells
Redaktor
Avatar
Odpovídá na g1ml1
coells:

:-D V tom případě hádám, že chyba bude tady: return AddEventClassTex­tAndIcon<Acci­dentInfo>(que­ry.ToList());

Neboli se snažíš vracet instanci typu List<AccidentInfo> a návratová hodnota je typu List<BasicInfo>.

 
Nahoru Odpovědět 3.1.2014 21:17
Avatar
g1ml1
Člen
Avatar
Odpovídá na coells
g1ml1:

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. :-)

 
Nahoru Odpovědět 3.1.2014 21:21
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.