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?

È stato utile?

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>();
            } 
        } 

    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top