propiedad property operator net c# .net casting type-conversion nullable

c# - property - Conversión inválida de ''System.Int32'' a ''System.Nullable`1[



propiedad nullable c# (3)

Para arriba simplemente podría escribir int? nVal = val

En realidad, tampoco puedes hacer eso. No hay conversión implícita de object a Nullable<int> . Pero hay una conversión implícita de int a Nullable<int> para que pueda escribir esto:

int? unVal = (int)val;

Puede usar el método Nullable.GetUnderlyingType .

Devuelve el argumento de tipo subyacente del tipo anulable especificado.

Una definición de tipo genérico es una declaración de tipo, como Nullable, que contiene una lista de parámetros de tipo, y la lista de parámetros de tipo declara uno o más parámetros de tipo. Un tipo genérico cerrado es una declaración de tipo donde se especifica un tipo particular para un parámetro de tipo.

Type t = typeof(int?); //will get this dynamically Type u = Nullable.GetUnderlyingType(t); object val = 5; //will get this dynamically object nVal = Convert.ChangeType(val, u);// nVal will be 5

Aquí una DEMO .

Type t = typeof(int?); //will get this dynamically object val = 5; //will get this dynamically object nVal = Convert.ChangeType(val, t);//getting exception here

Estoy obteniendo InvalidCastException en el código anterior. Para arriba simplemente podría escribir int? nVal = val int? nVal = val , pero el código anterior se está ejecutando dinámicamente.

Obtengo un valor (de tipo no anulable como int, float, etc.) envuelto en un objeto (aquí val), y tengo que guardarlo en otro objeto al convertirlo a otro tipo (que puede o no ser una versión que admite nulos) de eso). Cuando

Conversión inválida de ''System.Int32'' a ''System.Nullable`1 [[System.Int32, mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]]''.

Un int , debe ser convertible / type-convertible a nullable int , ¿cuál es el problema aquí?


Creo que debería explicar por qué la función no funciona:

1- La línea que arroja la excepción es la siguiente:

throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", new object[] { value.GetType().FullName, targetType.FullName }));

de hecho, la función de búsqueda en la matriz Convert.ConvertTypes después de eso, ve si el targer es un Enum y cuando no se encuentra nada arroja la excepción anterior.

2- Convert.ConvertTypes se inicializa como:

Convert.ConvertTypes = new RuntimeType[] { (RuntimeType)typeof(Empty), (RuntimeType)typeof(object), (RuntimeType)typeof(DBNull), (RuntimeType)typeof(bool), (RuntimeType)typeof(char), (RuntimeType)typeof(sbyte), (RuntimeType)typeof(byte), (RuntimeType)typeof(short), (RuntimeType)typeof(ushort), (RuntimeType)typeof(int), (RuntimeType)typeof(uint), (RuntimeType)typeof(long), (RuntimeType)typeof(ulong), (RuntimeType)typeof(float), (RuntimeType)typeof(double), (RuntimeType)typeof(decimal), (RuntimeType)typeof(DateTime), (RuntimeType)typeof(object), (RuntimeType)typeof(string) };

Entonces desde el int? no está en la matriz ConvertTypes y no hay un Enum. Se lanza la excepción.

Entonces, para reanudar, para que la función Convert.ChnageType funcione, tiene:

  1. El objeto a convertir es IConvertible

  2. El tipo de destino está dentro de ConvertTypes y no está Empty ni DBNull (hay una prueba de expulsión en esos dos con excepción de lanzamiento)

Este comportamiento se debe a que int (y todos los demás tipos predeterminados) utiliza la implementation. and here is the code of the Convert.DefaultToType como IConvertibale.ToType implementation. and here is the code of the implementation. and here is the code of the DefaultToType extracted usando ILSpy

internal static object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) { if (targetType == null) { throw new ArgumentNullException("targetType"); } RuntimeType left = targetType as RuntimeType; if (left != null) { if (value.GetType() == targetType) { return value; } if (left == Convert.ConvertTypes[3]) { return value.ToBoolean(provider); } if (left == Convert.ConvertTypes[4]) { return value.ToChar(provider); } if (left == Convert.ConvertTypes[5]) { return value.ToSByte(provider); } if (left == Convert.ConvertTypes[6]) { return value.ToByte(provider); } if (left == Convert.ConvertTypes[7]) { return value.ToInt16(provider); } if (left == Convert.ConvertTypes[8]) { return value.ToUInt16(provider); } if (left == Convert.ConvertTypes[9]) { return value.ToInt32(provider); } if (left == Convert.ConvertTypes[10]) { return value.ToUInt32(provider); } if (left == Convert.ConvertTypes[11]) { return value.ToInt64(provider); } if (left == Convert.ConvertTypes[12]) { return value.ToUInt64(provider); } if (left == Convert.ConvertTypes[13]) { return value.ToSingle(provider); } if (left == Convert.ConvertTypes[14]) { return value.ToDouble(provider); } if (left == Convert.ConvertTypes[15]) { return value.ToDecimal(provider); } if (left == Convert.ConvertTypes[16]) { return value.ToDateTime(provider); } if (left == Convert.ConvertTypes[18]) { return value.ToString(provider); } if (left == Convert.ConvertTypes[1]) { return value; } if (left == Convert.EnumType) { return (Enum)value; } if (left == Convert.ConvertTypes[2]) { throw new InvalidCastException(Environment.GetResourceString("InvalidCast_DBNull")); } if (left == Convert.ConvertTypes[0]) { throw new InvalidCastException(Environment.GetResourceString("InvalidCast_Empty")); } } throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", new object[] { value.GetType().FullName, targetType.FullName })); }

por otro lado, el elenco está implementado por la clase Nullable y la definición es:

public static implicit operator T?(T value) { return new T?(value); } public static explicit operator T(T? value) { return value.Value; }


Tienes que usar Nullable.GetUnderlyingType para obtener el tipo subyacente de Nullable .

Este es el método que utilizo para superar la limitación de ChangeType for Nullable

public static T ChangeType<T>(object value) { var t = typeof(T); if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { if (value == null) { return default(T); } t = Nullable.GetUnderlyingType(t); } return (T)Convert.ChangeType(value, t); }

método no genérico:

public static object ChangeType(object value, Type conversion) { var t = conversion; if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { if (value == null) { return null; } t = Nullable.GetUnderlyingType(t); } return Convert.ChangeType(value, t); }