Génériques

De Banane Atomic
Aller à la navigationAller à la recherche

Contrainte where

Csharp.svg
class MaClasse<T, U, V>
    where T : IInterface, new()
    where U : AutreClasse
    where V : class // par opposition à struct
{
    // La contrainte new() test si le type T a un constructeur sans argument ou un constructeur par défaut.
    // Sachant qu'un tel constructeur existe on peut l'utiliser.
    T item = new T();
}

Cast

Covariance et Contra variance

Csharp.svg
// un cast implicite d'un type int dans un type object
object o;
o = 0;

// pour les génériques ce n'est pas aussi simple
List<object> lo;
lo = new List<int>(); // impossible de convertir implicitement List<int> en List<object>
// normal car sinon on pourrait écrire le code suivant
lo.Add("MaChaine");
// ce qui reviendrait à ajouter un string dans une List de int

// il faut donc spécifier comment l'on souhaite convertir un int en object : méthode ConvertAll pour List
lo = new List<int>().ConvertAll(i => (object)i);


// par contre on peut écrire le code suivant, car on instancie une List d'object et non une List de int comme précédemment
var lo = new List<object>();
lo.Add(0);
lo.Add("MaChaine");

Implémentation d'un Convert like

Csharp.svg
// un cast un type int dans un type object
public class Generic<T>
{
    public T Value { get; set; }

    public Generic<TOutput> Convert<TOutput>(Converter<T, TOutput> converter)
    {
        if (converter == null)
        {
            throw new ArgumentNullException("converter");
        }
        var generic = new Generic<TOutput>();
        generic.Value = converter(this.Value);
        return generic;
    }
}

// Utilisation
Generic<object> gObject = new Generic<object>() { Value = 0 };

Generic<int> gInt = gObject.Convert(o => (int)o);

Default

Utile pour construire un objet T si l'on ne sait pas si T sera un type référence ou un type valeur.

Csharp.svg
public T GetValue<T>()
{
    ...
    return default(T);
}

Créer un type générique par réflexion

Les méthodes d'extension