Supponiamo di avere un metodo generico non vincolato che funziona su tutti i tipi che supportano l'uguaglianza. Esso esegue controlli di uguaglianza coppie e così lavora a O (n):Come invocare condizionalmente un metodo generico con vincoli?
public static int CountDuplicates<T>(IList<T> list)
{
/* ... */
}
Ho anche un metodo generico vincolato che funziona solo con i tipi di supporto di smistamento. Si parte da ordinare l'elenco in O (n log n), e poi conta tutti i duplicati in un solo passaggio:
public static int CountDuplicatesFast<T>(IList<T> list)
where T : IComparable<T>
{
/* ... */
}
Quindi, un chiamante può scegliere di richiamare il metodo veloce se è staticamente noto che la il tipo di elementi della lista supporta l'ordinamento. Potrebbe accadere che il chiamante stesso funzioni con lo IList<T>
generico dove T non è vincolato, quindi la sua unica opzione è di invocare il primo metodo (lento).
Ora, voglio il primo metodo per verificare in fase di runtime se il tipo T
in realtà implementa l'interfaccia IComparable<T>
e in caso affermativo, richiamare il metodo veloce:
public static int CountDuplicates<T>(IList<T> list)
{
if (typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
{
return CountDuplicatesFast(list);
}
else
{
/* use the slow algorithm */
}
}
Il problema è il compilatore rifiuta l'invocazione CountDuplicatesFast(list)
:
errore CS0314: il tipo 'T' non può essere utilizzato come parametro di tipo 'T' nel tipo generico o metodo 'Program.CountDuplicatesFast <T> (System.Collections.Generic.IList <T>) '. Non è prevista la conversione di boxe o la conversione del parametro di tipo da "T" a "System.IComparable <T>".
È possibile convincere il compilatore a fidarsi di me che so cosa sto facendo e di saltare il controllo dei vincoli?
Hai provato a utilizzare Cast? 'return CountDuplicatesFast (list.Cast>(). ToList());' –
Nevyn
@Nevyn che produce "Il tipo 'System.IComparable' non può essere utilizzato come parametro di tipo 'T' nel tipo generico o metodo 'UserQuery.MyType.CountDuplicatesFast (System.Collections.Generic.IList )'. Non esiste alcuna conversione implicita del riferimento da 'System.IComparable ' a 'System.IComparable >'. " –
Interessante. Quasi la traccia giusta, ma completamente l'esecuzione sbagliata.Suppongo che avrei bisogno di scrivere un programma di test e provare alcune cose diverse. Penso che il cast potrebbe essere in grado di farlo ... ma non ho idea di come esattamente ... oh, beh, per una prima ipotesi non era troppo lontano :-) – Nevyn