2009-08-15 13 views

Respuesta

62

Como realmente solo tiene que preocuparse por los tipos de valores (los tipos de referencia serán simplemente nulos), puede usar Activator.CreateInstance para llamar al constructor predeterminado.

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

Editar: Jon es (por supuesto) correcto. IsClass no es lo suficientemente exhaustivo - devuelve False si type es una interfaz.

+18

¡Mejor usar! Type.IsValueType, para hacer frente a las interfaces. –

+0

gracias muchachos! eso es lo que estaba buscando! –

1

Sin un genérico, no se puede garantizar que el tipo tiene un constructor sin parámetros, pero se puede buscar uno que utiliza la reflexión:

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

He intentado esto en una aplicación de consola, y se devuelve una instancia "predeterminada" de la clase — suponiendo que es una clase. Si necesita que funcione también para los tipos de referencia, necesitará una técnica adicional.

+3

El valor predeterminado para el tipo de referencia es nulo, y no es una instancia de la clase. Entonces, si hace lo que sugiere, GetDefault (T) devolverá nulo, mientras que GetDefault (Type) intentará crear una instancia, si es posible, lo cual es incorrecto. Tu técnica no es inútil, pero supongo que es más como un tipo de método "T GetInstance (T) donde T: new() {return new T();}". – JohannesH

+0

Veo a qué te refieres. ¡Gracias por la corrección! – harpo

+0

Tu respuesta es muy útil. – rolls

7

Así es como normalmente lo hago. Esto evita todo el 'IsValueType' o la búsqueda de problemas de constructores por completo.

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

¿Puede explicar cómo esto es diferente/mejor/peor que la respuesta de Mark Brackett? – rolls

+0

No puedo decir que sea mejor o peor; Depende de tus necesidades, supongo. Mi respuesta es casi seguramente más lenta sin ningún almacenamiento en caché. Lo que más me gusta de esta solución es que utiliza la función de lenguaje integrado que estamos tratando de emular; en lugar de simularlo – jonfuller

Cuestiones relacionadas