Il modo migliore per verificare se un tipo generico è una stringa?(C#)
Domanda
Ho una classe generica che dovrebbe consentire qualsiasi tipo, primitivo o altro.L'unico problema con questo è l'utilizzo default(T)
.Quando chiami default su un tipo di valore o una stringa, lo inizializza su un valore ragionevole (come una stringa vuota).Quando chiami default(T)
su un oggetto, restituisce null.Per vari motivi dobbiamo assicurarci che se non è un tipo primitivo, avremo un'istanza predefinita del tipo, non nullo.Ecco il tentativo 1:
T createDefault()
{
if(typeof(T).IsValueType)
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
}
Problema: la stringa non è un tipo di valore, ma non ha un costruttore senza parametri.Quindi, la soluzione attuale è:
T createDefault()
{
if(typeof(T).IsValueType || typeof(T).FullName == "System.String")
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
}
Ma questo sembra un errore.Esiste un modo più carino per gestire il caso delle stringhe?
Soluzione
Tieni presente che default(string) è null, non string.Empty.Potresti volere un caso speciale nel tuo codice:
if (typeof(T) == typeof(String)) return (T)(object)String.Empty;
Altri suggerimenti
if (typeof(T).IsValueType || typeof(T) == typeof(String))
{
return default(T);
}
else
{
return Activator.CreateInstance<T>();
}
Non testato, ma la prima cosa che mi è venuta in mente.
Puoi usare il TipoCodice enumerazione.Chiamare il metodo GetTypeCode sulle classi che implementano l'interfaccia IConvertible per ottenere il codice del tipo per un'istanza di tale classe.IConvertible è implementato da Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char e String, quindi puoi verificare la presenza di tipi primitivi utilizzando questo.Maggiori informazioni su "Controllo del tipo generico".
Personalmente, mi piace l'overload del metodo:
public static class Extensions {
public static String Blank(this String me) {
return String.Empty;
}
public static T Blank<T>(this T me) {
var tot = typeof(T);
return tot.IsValueType
? default(T)
: (T)Activator.CreateInstance(tot)
;
}
}
class Program {
static void Main(string[] args) {
Object o = null;
String s = null;
int i = 6;
Console.WriteLine(o.Blank()); //"System.Object"
Console.WriteLine(s.Blank()); //""
Console.WriteLine(i.Blank()); //"0"
Console.ReadKey();
}
}
La discussione per String non funziona qui.
Dovevo avere il seguente codice per i farmaci generici per farlo funzionare:
private T createDefault()
{
{
if(typeof(T).IsValueType)
{
return default(T);
}
else if (typeof(T).Name == "String")
{
return (T)Convert.ChangeType(String.Empty,typeof(T));
}
else
{
return Activator.CreateInstance<T>();
}
}
}