La meilleure façon de tester si un type générique est une chaîne ?(C#)

StackOverflow https://stackoverflow.com/questions/31498

  •  09-06-2019
  •  | 
  •  

Question

J'ai une classe générique qui devrait autoriser n'importe quel type, primitif ou autre.Le seul problème avec cela est d'utiliser default(T).Lorsque vous appelez default sur un type valeur ou une chaîne, il l'initialise à une valeur raisonnable (telle qu'une chaîne vide).Quand vous appelez default(T) sur un objet, il renvoie null.Pour diverses raisons, nous devons nous assurer que s'il ne s'agit pas d'un type primitif, nous aurons alors une instance par défaut du type, pas nul.Voici la tentative 1 :

T createDefault()
{
    if(typeof(T).IsValueType)
    {
        return default(T);
    }
    else
    {
        return Activator.CreateInstance<T>();
    }
}

Problème : la chaîne n'est pas un type valeur, mais elle n'a pas de constructeur sans paramètre.La solution actuelle est donc la suivante :

T createDefault()
{
    if(typeof(T).IsValueType || typeof(T).FullName == "System.String")
    {
        return default(T);
    }
    else
    {
        return Activator.CreateInstance<T>();
    }
}

Mais cela ressemble à une bidouille.Existe-t-il une façon plus agréable de gérer le cas des cordes ?

Était-ce utile?

La solution

Gardez à l'esprit que default(string) est null, pas string.Empty.Vous souhaiterez peut-être un cas particulier dans votre code :

if (typeof(T) == typeof(String)) return (T)(object)String.Empty;

Autres conseils

if (typeof(T).IsValueType || typeof(T) == typeof(String))
{
     return default(T);
}
else
{
     return Activator.CreateInstance<T>();
}

Non testé, mais c'est la première chose qui me vient à l'esprit.

Vous pouvez utiliser le TypeCode énumération.Appelez la méthode GetTypeCode sur les classes qui implémentent l'interface IConvertible pour obtenir le code de type d'une instance de cette classe.IConvertible est implémenté par Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char et String, vous pouvez donc vérifier les types primitifs en utilisant ceci.Plus d'informations sur "Vérification de type générique".

Personnellement, j'aime la surcharge de méthodes :

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 discussion sur String ne fonctionne pas ici.

Je devais avoir le code suivant pour les génériques pour que cela fonctionne -

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

    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top