texto significado refranes que mensaje implícito implicito implicita explícito ejemplos aprendizaje .net reflection type-conversion implicit-conversion

.net - significado - que es explícito



Cómo saber si el Tipo A es implícitamente convertible a Tipo B (3)

Dado Type a y Type b, ¿cómo puedo, en tiempo de ejecución, determinar si hay una conversión implícita de a a b?

Si eso no tiene sentido, considere el siguiente método:

public PropertyInfo GetCompatibleProperty<T>(object instance, string propertyName) { var property = instance.GetType().GetProperty(propertyName); bool isCompatibleProperty = !property.PropertyType.IsAssignableFrom(typeof(T)); if (!isCompatibleProperty) throw new Exception("OH NOES!!!"); return property; }

Y aquí está el código de llamada que quiero que funcione:

// Since string.Length is an int property, and ints are convertible // to double, this should work, but it doesn''t. :-( var property = GetCompatibleProperty<double>("someStringHere", "Length");


Conversiones implícitas que deberá tener en cuenta:

  • Identidad
  • sbyte a corto, int, largo, flotante, doble o decimal
  • byte a short, ushort, int, uint, long, ulong, float, double o decimal
  • corto a int, largo, flotante, doble o decimal
  • ushort a int, uint, long, ulong, float, doble o decimal
  • int a largo, flotante, doble o decimal
  • uint a long, ulong, float, double o decimal
  • largo para flotar, doble o decimal
  • ulong para flotar, doble o decimal
  • char para ushort, int, uint, long, ulong, float, doble o decimal
  • flotar para duplicar
  • Conversión de tipo anulable
  • Tipo de referencia al objeto
  • Clase derivada a clase base
  • Clase a la interfaz implementada
  • Interfaz a la interfaz base
  • Matriz a matriz cuando las matrices tienen el mismo número de dimensiones, hay una conversión implícita del tipo de elemento de origen al tipo de elemento de destino y el tipo de elemento de origen y el tipo de elemento de destino son tipos de referencia
  • Tipo de matriz a System.Array
  • Tipo de matriz para IList <> y sus interfaces base
  • Delegar tipo a System.Delegate
  • Conversión del boxeo
  • Enum tipo a System.Enum
  • Conversión definida por el usuario (op_implicit)

Supongo que estás buscando lo último. Tendrá que escribir algo parecido a un compilador para cubrir todos ellos. Notable es que System.Linq.Expressions.Expression no intentó esta hazaña.


La respuesta aceptada a esta pregunta maneja muchos casos, pero no todos. Por ejemplo, aquí hay solo algunas conversiones / conversiones válidas que no se manejan correctamente:

// explicit var a = (byte)2; var b = (decimal?)2M; // implicit double? c = (byte)2; decimal? d = 4L;

A continuación, publiqué una versión alternativa de esta función que responde específicamente a la cuestión de los moldes IMPLICIT y las conversiones. Para obtener más detalles, el banco de pruebas que utilicé para verificarlo y la versión de casting EXPLICIT, consulte mi publicación sobre el tema .

public static bool IsImplicitlyCastableTo(this Type from, Type to) { // from http://www.codeducky.org/10-utilities-c-developers-should-know-part-one/ Throw.IfNull(from, "from"); Throw.IfNull(to, "to"); // not strictly necessary, but speeds things up if (to.IsAssignableFrom(from)) { return true; } try { // overload of GetMethod() from http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/ // that takes Expression<Action> ReflectionHelpers.GetMethod(() => AttemptImplicitCast<object, object>()) .GetGenericMethodDefinition() .MakeGenericMethod(from, to) .Invoke(null, new object[0]); return true; } catch (TargetInvocationException ex) { return = !( ex.InnerException is RuntimeBinderException // if the code runs in an environment where this message is localized, we could attempt a known failure first and base the regex on it''s message && Regex.IsMatch(ex.InnerException.Message, @"^The best overloaded method match for ''System.Collections.Generic.List<.*>.Add(.*)'' has some invalid arguments$") ); } } private static void AttemptImplicitCast<TFrom, TTo>() { // based on the IL produced by: // dynamic list = new List<TTo>(); // list.Add(default(TFrom)); // We can''t use the above code because it will mimic a cast in a generic method // which doesn''t have the same semantics as a cast in a non-generic method var list = new List<TTo>(capacity: 1); var binder = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember( flags: CSharpBinderFlags.ResultDiscarded, name: "Add", typeArguments: null, context: typeof(TypeHelpers), // the current type argumentInfo: new[] { CSharpArgumentInfo.Create(flags: CSharpArgumentInfoFlags.None, name: null), CSharpArgumentInfo.Create( flags: CSharpArgumentInfoFlags.UseCompileTimeType, name: null ), } ); var callSite = CallSite<Action<CallSite, object, TFrom>>.Create(binder); callSite.Target.Invoke(callSite, list, default(TFrom)); }


Tenga en cuenta que IsAssignableFrom NO resuelve su problema. Tienes que usar Reflection como tal. Tenga en cuenta la necesidad explícita de manejar los tipos primitivos; estas listas son por §6.1.2 (conversiones numéricas implícitas) de la especificación.

static class TypeExtensions { static Dictionary<Type, List<Type>> dict = new Dictionary<Type, List<Type>>() { { typeof(decimal), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char) } }, { typeof(double), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char), typeof(float) } }, { typeof(float), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char), typeof(float) } }, { typeof(ulong), new List<Type> { typeof(byte), typeof(ushort), typeof(uint), typeof(char) } }, { typeof(long), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(char) } }, { typeof(uint), new List<Type> { typeof(byte), typeof(ushort), typeof(char) } }, { typeof(int), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(char) } }, { typeof(ushort), new List<Type> { typeof(byte), typeof(char) } }, { typeof(short), new List<Type> { typeof(byte) } } }; public static bool IsCastableTo(this Type from, Type to) { if (to.IsAssignableFrom(from)) { return true; } if (dict.ContainsKey(to) && dict[to].Contains(from)) { return true; } bool castable = from.GetMethods(BindingFlags.Public | BindingFlags.Static) .Any( m => m.ReturnType == to && (m.Name == "op_Implicit" || m.Name == "op_Explicit") ); return castable; } }

Uso:

bool b = typeof(A).IsCastableTo(typeof(B));