web-dev-qa-db-fra.com

Existe-t-il une approche raisonnable des paramètres de type "par défaut" dans C # Generics?

Dans les modèles C++, on peut spécifier qu'un certain type de paramètre est par défaut. C'est à dire. sauf indication contraire explicite, il utilisera le type T.

Cela peut-il être fait ou approximé en C #?

Je cherche quelque chose comme:

public class MyTemplate<T1, T2=string> {}

Pour qu'une instance du type qui ne spécifie pas explicitement T2:

MyTemplate<int> t = new MyTemplate<int>();

Serait essentiellement:

MyTemplate<int, string> t = new MyTemplate<int, string>();

En fin de compte, je regarde un cas dans lequel il existe un modèle qui est assez largement utilisé, mais j'envisage d'étendre avec un paramètre de type supplémentaire. Je pourrais sous-classer, je suppose, mais j'étais curieux de savoir s'il y avait d'autres options dans cette veine.

77
el2iot2

Le sous-classement est la meilleure option.

Je sous-classerais votre classe générique principale:

class BaseGeneric<T,U>

avec une classe spécifique

class MyGeneric<T> : BaseGeneric<T, string>

Cela permet de conserver facilement votre logique au même endroit (la classe de base), mais aussi de fournir facilement les deux options d'utilisation. Selon la classe, il y a probablement très peu de travail supplémentaire nécessaire pour y arriver.

70
Reed Copsey

Une solution est le sous-classement. Une autre que j'utiliserais à la place, ce sont les méthodes d'usine (combinées avec le mot-clé var).

public class MyTemplate<T1,T2>
{
     public MyTemplate(..args..) { ... } // constructor
}

public static class MyTemplate{

     public static MyTemplate<T1,T2> Create<T1,T2>(..args..)
     {
         return new MyTemplate<T1, T2>(... params ...);
     }

     public static MyTemplate<T1, string> Create<T1>(...args...)
     {
         return new MyTemplate<T1, string>(... params ...);
     }
}

var val1 = MyTemplate.Create<int,decimal>();
var val2 = MyTemplate.Create<int>();

Dans l'exemple ci-dessus val2 est de type MyTemplate<int,string>et non un type qui en dérive.

Un type class MyStringTemplate<T>:MyTemplate<T,string> n'est pas du même type que MyTemplate<T,string>. Cela pourrait poser des problèmes dans certains scénarios. Par exemple, vous ne pouvez pas caster une instance de MyTemplate<T,string> à MyStringTemplate<T>.

18
Thanasis Ioannidis

vous pouvez également créer une surcharge de classe comme ça

public class MyTemplate<T1, T2> {
    public T1 Prop1 { get; set; }
    public T2 Prop2 { get; set; }
}

public class MyTemplate<T1> : MyTemplate<T1, string>{}
11
Moes

C # ne prend pas en charge une telle fonctionnalité.

Comme vous l'avez dit, vous pouvez le sous-classer (s'il n'est pas scellé et dupliquer toutes les déclarations de constructeur) mais c'est une chose complètement différente.

8
Mehrdad Afshari

Malheureusement, C # ne prend pas en charge ce que vous essayez de faire. Ce serait une fonctionnalité difficile à implémenter étant donné que le type par défaut pour un paramètre devrait respecter les contraintes génériques et créerait très probablement des maux de tête lorsque le CLR tenterait d'assurer la sécurité du type.

2
Andrew Hare