Contrainte where
|
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
|
// 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
|
// 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);
|
Utile pour construire un objet T si l'on ne sait pas si T sera un type référence ou un type valeur.
|
public T GetValue<T>()
{
...
return default(T);
}
|