Estoy usando la reflexión para recorrer Type
las propiedades de una y establecer ciertos tipos a sus valores predeterminados. Ahora, podría cambiar el tipo y configurarlo default(Type)
explícitamente, pero prefiero hacerlo en una línea. ¿Existe un equivalente programático del incumplimiento?
c#
reflection
default
etiquetas2k
fuente
fuente
Respuestas:
En la versión más reciente de .net, como .net standard,
type.IsValueType
debe escribirse comotype.GetTypeInfo().IsValueType
fuente
default(T) != (T)(object)default(T) && !(default(T) != default(T))
tiene un argumento, de lo contrario, no importa si está encuadrado o no, ya que son equivalentes.default(T) != default(T)
return sea falso, y eso es hacer trampa! =)Array.CreateInstance(type, length)
.¿Por qué no llamar al método que devuelve default (T) con reflexión? Puede usar GetDefault de cualquier tipo con:
fuente
nameof(GetDefaultGeneric)
si puedes, en lugar de"GetDefaultGeneric"
Puedes usar
PropertyInfo.SetValue(obj, null)
. Si se llama a un tipo de valor, le dará el valor predeterminado. Este comportamiento está documentado en .NET 4.0 y en .NET 4.5 .fuente
Si está utilizando .NET 4.0 o superior y desea una versión programática que no sea una codificación de reglas definidas fuera del código , puede crear
Expression
, compilar y ejecutar sobre la marcha.El siguiente método de extensión tomará ay
Type
obtendrá el valor devuelto adefault(T)
través delDefault
método en laExpression
clase:También debe almacenar en caché el valor anterior en función del
Type
, pero tenga en cuenta que si llama a esto para una gran cantidad deType
instancias, y no lo usa constantemente, la memoria consumida por la memoria caché podría superar los beneficios.fuente
e.Compile()
. Ese es todo el punto de las expresiones.e.Compile()
debe almacenarse en caché, pero suponiendo que este método sea aproximadamente 14 veces más rápido, por ejemplolong
. Consulte gist.github.com/pvginkel/fed5c8512b9dfefc2870c6853bbfbf8b para obtener el punto de referencia y los resultados.e.Compile()
lugar dee.Compile()()
? es decir, ¿puede cambiar el tipo predeterminado de un tipo en tiempo de ejecución? Si no (como creo que es el caso), simplemente puede almacenar el resultado en caché en lugar de la expresión compilada, lo que debería mejorar aún más el rendimiento.¿Por qué dice que los genéricos están fuera de la imagen?
fuente
Esta es la solución optimizada de Flem:
fuente
return type.IsValueType ? typeDefaults.GetOrAdd(type, Activator.CreateInstance) : null;
La respuesta elegida es una buena respuesta, pero tenga cuidado con el objeto devuelto.
Extrapolando ...
fuente
Las expresiones pueden ayudar aquí:
No probé este fragmento, pero creo que debería producir nulos "tipados" para los tipos de referencia.
fuente
"typed" nulls
- explique. ¿Qué objeto estás devolviendo? Si devuelve un objeto de tipotype
, pero su valor esnull
, entonces no tiene, no puede tener, ninguna otra información que no sea esanull
. No puede consultar unnull
valor y averiguar qué tipo es supuestamente. Si NO devuelve nulo, pero regresa ... No sé qué ..., entonces no actuará comonull
.Todavía no puedo encontrar nada simple y elegante, pero tengo una idea: si conoce el tipo de propiedad que desea establecer, puede escribir la suya
default(T)
. Hay dos casos:T
es un tipo de valor yT
es un tipo de referencia. Puedes ver esto marcandoT.IsValueType
. SiT
es un tipo de referencia, simplemente puede establecerlo ennull
. SiT
es un tipo de valor, tendrá un constructor sin parámetros predeterminado al que puede llamar para obtener un valor "en blanco".fuente
Hago la misma tarea así.
fuente
Equivalente a la respuesta de Dror pero como método de extensión:
fuente
Pequeños ajustes a la solución de @Rob Fonseca-Ensor : El siguiente método de extensión también funciona en .Net Standard ya que uso GetRuntimeMethod en lugar de GetMethod.
... y la prueba de unidad correspondiente para aquellos que se preocupan por la calidad:
fuente
fuente
Nullable<T>
tipos: no devuelve el equivalente de lodefault(Nullable<T>)
que debería sernull
. La respuesta aceptada por Dror funciona mejor.Esto debería funcionar:
Nullable<T> a = new Nullable<T>().GetValueOrDefault();
fuente