9
votes

Comment obtenir la valeur par défaut pour un type de valeur avec réflexion

Si j'ai un paramètre de type générique qui est un type de valeur et que je veux savoir si une valeur est égale à la valeur par défaut, je le teste comme ceci:

static bool IsDefault(object value){
   if(!(value is ValueType)){
      throw new ArgumentException("Precondition failed: Must be a ValueType", "value");
   }
   var @default = Activator.CreateInstance(value.GetType());
   return value.Equals(@default);  
}


3 commentaires

Regarde bien pour moi. Bonne chose que la valeur est valueType Test vérifiera également null . :)


Deux questions: 1. Pourquoi ne pas utiliser la méthode générique? 2. Pourquoi ne pas faire le paramètre à la deuxième méthode a valeur de valeur car vous allez simplement vous plaindre de toute façon?


Ou faire si (! (Valeur est valuelette)) Valeur de retour == null;


4 Réponses :


2
votes

Je voudrais demander valueltype comme paramètre à simplifier: xxx


1 commentaires

Le commentaire de Cdhowie m'a repensé cette solution, car il ne gère pas le potentiel NullReferenceException . Assurez-vous de gérer ce cas ou lancez un argumentnulxception si le paramètre est null.



0
votes

sur une note latérale, y a-t-il quelque chose que je ne considère pas ici avec respect d'évaluer des structures nullables?

Oui, vous manquez quelque chose. En prenant un objet car le paramètre dans vous nécessite un code d'appel à la case NULLABLABLE (qui les convertit sur NULL ou à leur t Valeur). Donc, si vous passez une nullable, votre est / lancer va lancer car null ne sera jamais de type de valeur.

EDIT: Comme @CDHOWIE dit, vous devrez vérifier NULL. Cela fonctionnera également pour des types nullables.


1 commentaires

Une autre chose à considérer avec des structures nullables est qu'il n'ya aucun moyen de faire la distinction entre par exemple. un int avec valeur zéro et un int? avec valeur zéro, même si zéro est la valeur par défaut du premier de ces types, mais n'est pas la valeur par défaut pour la seconde .



8
votes

J'ai trouvé utile les méthodes d'extension suivantes et fonctionnera pour tous les types:

public static object GetDefault(this Type t)
{
    return t.IsValueType ? Activator.CreateInstance(t) : null;
}

public static T GetDefault<T>()
{
    var t = typeof(T);
    return (T) GetDefault(t);
}

public static bool IsDefault<T>(T other)
{
    T defaultValue = GetDefault<T>();
    if (other == null) return defaultValue == null;
    return other.Equals(defaultValue);
}


2 commentaires

Cela ne semble pas fonctionner dans un scénario de réflexion pur où vous ne connaissez pas le type de l'un ni l'autre, celui qui arrive est un objet. Donc, le t in isdefault est juste objet, et .equals vérifie juste pour l'égalité de référence. Au moins dans mon cas boxé 0 n'était pas égal à activator.createinstance (propriété.propertytype) ithathtype est int


J'ai essayé votre solution et j'ai trouvé encore plus court (je crois que cela devrait bien fonctionner aussi): Objet statique public getDefault (T Obj) {renvoyer défaut (t); }



4
votes

Une ancienne question mais la réponse acceptée ne fonctionne pas pour moi, donc je soumets cela (peut probablement être amélioré):

typeof(int).GetDefault();       // returns 0
typeof(int?).GetDefault();      // returns 0
typeof(DateTime).GetDefault();  // returns 01/01/0001 00:00:00
typeof(DateTime?).GetDefault(); // returns 01/01/0001 00:00:00
typeof(string).GetDefault();    // returns null
typeof(Exception).GetDefault(); // returns null


1 commentaires

Fyi, c'est la réponse.