Ho funzioni pubbliche in questo modo:compilatore non chiama appropriata sovraccarico generico quando viene passato con il tipo di valore
public static T Get<T>(this Mango m, T defaultValue = default(T)) where T : class
{
//do something; return something;
}
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct
{
//do something; return something;
}
Fondamentalmente voglio gestire individualmente i tipi di riferimento e tipi nullable. Compila; fino a quando non chiedo i tipi di valore. Per i tipi di riferimento che compila.
mango.Get<string>(); // compiles..
mango.Get(""); // compiles..
mango.Get<int>(); // The type 'int' must be a reference type in order to use it as
// parameter 'T' in the generic type or method Get<T>(Mango, T)
//also // The call is ambiguous between the following methods or properties:
// Get<int>(Mango, int) and Get<int>(Mango, int?)
Quale vera ambiguità è qui? Quando T
è int
, non si può chiamare correttamente il sovraccarico della struct? anche:
mango.Get<int>(0); // The type 'int' must be a reference type in order to use it as
// parameter 'T' in the generic type or method Get<T>(Mango, T)
Perché il compilatore rilevare solo il sovraccarico di tipo di riferimento? Ho provato avente due overload distinte:
public static T Get<T>(this Mango m) where T : class
{
return default(T);
}
public static T? Get<T>(this Mango m) where T : struct
{
return default(T);
}
public static T Get<T>(this Mango m, T def) where T : class
{
return default(T);
}
public static T? Get<T>(this Mango m, T? def) where T : struct
{
return default(T);
}
Il problema persisteva. Ovviamente, i primi due metodi non vengono compilati qui poiché l'overloading non funziona semplicemente sulla base di vincoli.
ho provato rimuovendo la class
sovraccarico vincolata e mantenendo solo il struct
costretto uno, in questo modo:
public static T? Get<T>(this Mango m, T? defaultValue = default(T?)) where T : struct
{
//do something; return something;
}
mango.Get<int>(); // voila compiles!
mango.Get<int>(0); // no problem at all..
// but now I can't have mango.Get<string>() for instance :(
Perchè sono solo a sinistra con la ridenominazione le due funzioni? Mi sembra appropriato avere un nome unificato in modo che il chiamante non debba preoccuparsi dei dettagli dell'implementazione, ma chiama semplicemente Get
per qualsiasi tipo.
Aggiornamento: La soluzione di Marc non funziona se devo evitare il parametro opzionale.
mango.Get<int>(); // still wouldnt work!!
Ma c'è di più magico :(:(
public static bool IsIt<T>(this T? obj) where T : struct
{
return who knows;
}
public static bool IsIt<T>(this T obj) where T : class
{
return perhaps;
}
Con tutti i mezzi mi aspetto lo stesso bug del compilatore (secondo me) a darmi fastidio. Ma no funziona questa volta .
Guid? g = null;
g.IsIt(); //just fine, and calls the struct constrained overload
"abcd".IsIt(); //just fine, and calls the class constrained overload
Quindi, se la risoluzione di sovraccarico viene prima di controllo dei vincoli come dice Marc, non dovrei ottenere lo stesso errore anche questa volta? Ma no. Perché è così?? Che diavolo sta succedendo? : x
A metà del post, stavo per suggerire di provare solo la versione della struct, ma l'hai già fatto e lo compila. _Seems_ per me questo è un bug reale e dovrebbe essere segnalato. –
@JohnWillemse: Nessun bug, vedere la risposta di Marcs. –
@DanielHilgarth non può essere un bug, ma sicuramente se fosse supportato questa potrebbe essere stata una caratteristica utile! – nawfal