2009-08-15 8 views
37

Si je veux une méthode qui retourne la valeur par défaut d'un type donné et la méthode est générique je peux retourner une valeur par défaut comme ceci:comment obtenir la valeur par défaut d'un type si le type est seulement connu comme System.Type?

public static T GetDefaultValue() 
{ 
    return default(T); 
} 

Puis-je faire quelque chose de similaire au cas où j'ai le type seulement comme un objet System.Type?

public static object GetDefaultValue(Type type) 
{ 
    //??? 
} 

Répondre

62

Étant donné que vous ne devez vous soucier que des types de valeurs (les types de référence seront simplement null), vous pouvez utiliser Activator.CreateInstance pour appeler le constructeur par défaut.

public static object GetDefaultValue(Type type) { 
    return type.IsValueType ? Activator.CreateInstance(type) : null; 
} 

Édition: Jon est (bien sûr) correct. IsClass n'est pas assez exhaustive - il renvoie False si type est une interface.

+18

Mieux vaut utiliser! Type.IsValueType, pour faire face aux interfaces. –

+0

merci les gars! c'est ce que je cherchais! –

1

Sans générique, vous ne pouvez pas garantir que le type a un constructeur sans paramètre, mais vous pouvez rechercher un utilisant la réflexion:

public static object GetDefaultValue(Type type) 
{ 
    ConstructorInfo ci = type.GetConstructor(new Type[] {}); 
    return ci.Invoke(new object[] {}); 
} 

J'ai essayé dans une application de la console, et renvoie une instance "par défaut" de la classe — en supposant que c'est une classe. Si vous en avez également besoin, vous aurez besoin d'une technique supplémentaire.

+3

Donc, s'il fait ce que vous suggérez GetDefault (T) renverra null tandis que GetDefault (Type) essaiera de créer une instance si possible, ce qui est faux. Votre technique n'est pas inutile mais je suppose que cela ressemble plus à un "T GetInstance (T) où T: nouveau() {return new T();}" type de méthode. – JohannesH

+0

Je vois ce que tu veux dire. Merci pour la correction! – harpo

+0

Votre réponse est très utile. – rolls

7

Voici comment je le fais normalement. Cela évite l'ensemble de 'IsValueType' ou la recherche de problèmes de constructeurs. La valeur par défaut pour le type de référence est null, et non une instance de la classe

public static object MakeDefault(this Type type) 
{ 
    var makeDefault = typeof(ExtReflection).GetMethod("MakeDefaultGeneric"); 
    var typed = makeDefault.MakeGenericMethod(type); 
    return typed.Invoke(null, new object[] { }); 
} 

public static T MakeDefaultGeneric<T>() 
{ 
    return default(T); 
} 
+0

Pouvez-vous expliquer en quoi cela est différent/meilleur/pire que Mark Brackett? – rolls

+0

Je ne peux pas dire que c'est mieux ou pire; dépend de vos besoins, je suppose. Ma réponse est presque certainement plus lente sans aucune mise en cache. La seule chose que j'aime particulièrement dans cette solution, c'est qu'elle utilise la fonction de langage intégrée que nous essayons d'émuler; plutôt que de le simuler. – jonfuller