Esiste un approccio ragionevole ai parametri di tipo “default” in C # Generics?
-
22-08-2019 - |
Domanda
In template C ++, si può specificare che un certo tipo di parametro è un valore predefinito. Cioè se non esplicitamente specificato, verrà utilizzato il tipo T.
Può questo essere fatto o approssimata in C #?
Sto cercando qualcosa di simile:
public class MyTemplate<T1, T2=string> {}
In modo che un'istanza del tipo che non specifica esplicitamente T2
:
MyTemplate<int> t = new MyTemplate<int>();
Sarebbe essenzialmente:
MyTemplate<int, string> t = new MyTemplate<int, string>();
In definitiva sto guardando un caso in cui v'è un modello che è abbastanza ampiamente utilizzato, ma sto considerando l'espansione con un parametro di tipo aggiuntivo. Potrei sottoclasse immagino, ma ero curioso di sapere se c'erano altre opzioni in questa vena.
Soluzione
Subclassing è l'opzione migliore.
Vorrei sottoclasse la classe generica principale:
class BaseGeneric<T,U>
con una classe specifica
class MyGeneric<T> : BaseGeneric<T, string>
In questo modo è facile mantenere la logica in un unico luogo (la classe base), ma anche facile da fornire entrambe le opzioni di utilizzo. A seconda della classe, c'è probabilmente molto poco lavoro aggiuntivo necessario per rendere questo accada.
Altri suggerimenti
Una soluzione è la creazione di sottoclassi. Un altro userei invece, è metodi di fabbrica (in combinazione con var parola chiave).
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>();
Nell'esempio precedente val2
è di tipo MyTemplate<int,string>
e non un tipo derivato da esso.
Un tipo class MyStringTemplate<T>:MyTemplate<T,string>
non è dello stesso tipo di MyTemplate<T,string>
.
Questo potrebbe comportare alcuni problemi in alcuni scenari.
Per esempio non è possibile lanciare un'istanza di MyTemplate<T,string>
a MyStringTemplate<T>
.
è anche possibile creare un sovraccarico di classe in questo modo
public class MyTemplate<T1, T2> {
public T1 Prop1 { get; set; }
public T2 Prop2 { get; set; }
}
public class MyTemplate<T1> : MyTemplate<T1, string>{}
C # non supporta tale caratteristica.
Come hai detto, è possibile creare una sottoclasse (se non è sigillato, e duplicare tutte le dichiarazioni del costruttore), ma è una cosa completamente diversa.
Purtroppo C # non supporta ciò che si sta cercando di fare. Sarebbe una caratteristica difficile da attuare, dato che il tipo predefinito per un parametro dovrebbe rispettare i vincoli generici e molto probabilmente creare mal di testa quando il CLR ha cercato di garantire la tipo di sicurezza.