dotNed

Welkom bij dotNed Inloggen | Aanmelden | Help
in Zoeken

Even Lijkt Elke Voortgang Een Logische Daad

Gek van Generic-s

Ik loop inmiddels al weer een week of drie echt met generics te spelen. Eigenlijk heb ik er echt invulling aan gegeven op de Code-Camp, alwaar ik heerlijk heb kunnen sparren met Peter Schipper en Dennis Vroegop. Nu ook in de mailing van Marcel Peereboom een referentie stond naar Generics, dacht ik het hoog tijd om maar eens te gaan bloggen.

Punt wat ik ga maken: class MyClass : GenericType<MyClass, IGenericBaseClass<MyClass>>

Ik heb eerst een model gemaakt:

class MyClass : GenericClass<T> where T : MyBaseClass, IMyBaseClass

waarin GenericClass ge generieke toepassing van de class is en T een overerving van MyBaseClass en ten minste IMyBaseClass implementeerd. Ik wilde echter de toegevoegde waarde: properties en methods juist in de GenericClass plaatsen. Ik heb die nu in de MyBaseClass staan. De IMyBaseClass maakt ook nog eens gebruik van de MyBaseClass. Dit leidde tot:

class MyClass : GenericClass<T> where T : MyBaseClass, IGenericBaseClass<MyBaseClass>

Echter de implementatie van de IGenericBaseClass<MyBaseClass> staat juist in de MyBaseClass en niet in GenericClass, waar ik het wel wil gebruiken, maar dat kan weer niet: Generics geven toegevoegde waarde maar zijn agnostisch voor wat betreft het meegegeven Type. Ergo ik moet een manier vinden om de toegevoegde waarde van de interface en van de baseclass in de generic type te krijgen en alles daar implementeren dat leidt tot minder code. Een dagje code prutsen en een paar typefouten later blijkt toevallig het volgende statement te compileren:

class MyClass : GenericClass<MyClass> where MyClass : IGenericBaseClass<MyBaseClass>

Dit geeft te denken dat ik opeens De implementatie van de interface maar 1 keer hoef te doen. de GenericClass vertellen welke properties en methods er zijn op het meegegeven type geeft voldoende mogelijkheid om deze in de GenericClass te kunnen gebruiken. Bijvoorbeeld:

interface IGenericBaseClass<T>
{
    ...
    T Copy();
}

class GenericClass<T> where T : IGenericBaseClass<T>, new()
{
    ...
    T IGenericBaseClass<T>.Copy()
    {
        // for demo purpose only
        return new T();
    }
}

Wanneer ik nu class MyClass : GenericType<MyClass, IGenericBaseClass<MyClass>> uit het eerste statement gebruik kom ik nog een stukje dichter bij waar ik zijn wil: een manier om De implementatie van de interface en het type te gebruiken in de generic. het voorbeeld wordt dan als volgt:

interface IGenericBaseClass<T>
{
    ...
    T Copy();
}

class GenericClass<T, IMyBaseClass> where T : new() where IMyBaseClass : IGenericBaseClass<T>
{
    ...
    T IGenericBaseClass<T>.Copy()
    {
        // for demo purpose only
        return new T();
    }
}

Ik ben er nog niet helemaal uit welke voordelen ik hier nog meer uit kan halen behalve dat ik nu de interface zelf kan definieren, en mee kan geven aan de generic. Waarbij ik de inhoud van IGenericBaseClass<T> als minimale interface mag veronderstellen, en alles daarvan mag gebruiken. Dit geeft mij meer flexibiliteit. En daar gaat het tenslotte om.

Wie weet komen er nog meer leuke uitbreidingen op deze strategie.

Published Monday, June 18, 2007 10:13 PM door Rolf Eleveld

Comments

 

Rolf Eleveld said:

Goed om te weten dat andere met dezelfde zaken bezig zijn: http://brennan.offwhite.net/blog/2007/06/27/a-bug-with-reflection-and-inheritance/ Dit maakt een generic class definitie:
class GenClass<T> where T : GenClass<T>{ }
June 30, 2007 2:00 PM
Anonymous comments are disabled

This Blog

Post Calendar

<June 2007>
SuMoTuWeThFrSa
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

Syndication

Powered by Community Server, by Telligent Systems