webForumDet fria alternativet

Casta en generisk lista (basklasser) till en annan generisk (subklasser)

.NET

2 svar · 597 visningar · startad av Lukaspojken

Medlem sedan maj 20011 312 inlägg
Frågan#1

Finns det nåt smart sätt att casta en generisk lista innehållande basklasser till en generisk klass med subklasser?

List<ErrandBase> errandBases --- Den generiska listan innehåller enbart ErrandOrder. ErrandOrder ärver från ErrandBase.

Det jag skulle vilja göra är:
List<ErrandOrder> errandOrders = (List<ErrandOrder>)errandBases;

Men detta fungerar inte. Sättet jag fått lösa det idag är att loopa ut errandBases och lägga till dessa i errandOrders-listan. Detta vill jag slippa göra men jag är osäker på hur jag lösa det. Några förslag?

Medlem sedan feb. 200563 inlägg
#2

Lukaspojken skrev:

Finns det nåt smart sätt att casta en generisk lista innehållande basklasser till en generisk klass med subklasser?

List<ErrandBase> errandBases --- Den generiska listan innehåller enbart ErrandOrder. ErrandOrder ärver från ErrandBase.

Det jag skulle vilja göra är:
List<ErrandOrder> errandOrders = (List<ErrandOrder>)errandBases;

Men detta fungerar inte. Sättet jag fått lösa det idag är att loopa ut errandBases och lägga till dessa i errandOrders-listan. Detta vill jag slippa göra men jag är osäker på hur jag lösa det. Några förslag?

Följande bör nog fungera, så länge som du nu verkligen har ErrandOrder i alla listans element, men annars blir det förstås ett 'InvalidCastException':

List<ErrandOrder> errandOrders = errandBases.ConvertAll(
    delegate(ErrandBase errandBase)
    {
        return (ErrandOrder)errandBase;
    }
);

Dock tvivlar jag på att downcasting är den bästa lösningen, utan det går antagligen att ändra koden så att du aldrig behöver casta den eftersom du säger att du vet att den alltid innehåller samma subklass.

Den naturliga frågan som infinner sig är alltså att om man nu verkligen vet att samtliga instanser alltid innehåller ErrandOrder, varför då inte typa listan som just en List<ErrandOrder> i stället för en List<ErrandBase> som måste downcastas ?

Om anledningen är att listan ska skickas in till en metod, som även skall kunna hantera listor med andra subtyper, så kanske den har följande typ av signatur:
public void doSomethingWithErrandBases(List<ErrandBase> errandBases)
och den går då inte att anropa med en paramer typad som List<ErrandOrder> vilket skulle kunna vara en anledning till att vilja skapa en lista med element typade som bastypen.
Men då kanske det i stället går att använda följande signatur:
public void doSomethingWithErrandBases<T>(List<T> errandBases) where T : ErrandBase
och skicka in sin list-parameter som förhoppningsvis hela tiden kan vara typad som en "List<ErrandOrder>" utan något behov av att skapa en List<ErrandBase> som sedan måste downcastas ?

Medlem sedan maj 20011 312 inlägg
#3

Tack för ditt svar!

Anledningen för att jag vill downcasta är för att jag har ca 20 andra ärendetyper. Jag vill helst ha en mappningsmetod i mitt repository som returnerar en lista av errandbases. Men sedan har jag en service-metod som tex returnerar en lista av ErrandOrders. Jag vill inte ha en ny mappningsmetod i repository som returnerar ErrandOrders. Det känns som det blir dubblicering av kod. Eller finns det något smart sätt man kan lösa detta?

261 ms totalt · 4 externa anrop · v20260731065814-full.1dc6f849
119 ms — deklarationer (db)
0 ms — hämta statistik (cache)
134 ms — hämta tråd, inlägg och bilagor (db)
124 ms — ändringar (db)