type number convert conversion cast c# unboxing

convert - number c#



¿Cómo unboxear del objeto para escribirlo contiene, sin saber ese tipo en tiempo de compilación? (8)

En el tiempo de ejecución me aparece la instancia en caja de algún tipo. ¿Cómo desempaquetarlo al tipo subyacente?

Object obj; String variable = "Some text"; obj = variable // boxing; // explicit unboxing, because we know the type of variable at compile time. var x = (String)obj // Now let''s pretend that we don''t know the type of underlying object at compile time. Type desiredType = obj.GetType(); // But we can figure out. //And now the question. //How to express something like this: var y = (desiredType)obj; //Need to get unboxed instance of initial variable here;


Ahora supongamos que se produce el boxeo real:

int v = 5; object o = v; //boxed Type type = o.GetType(); //will return typeof(int) int convertedBack = (int)Convert.ChangeType(o, type); Console.WriteLine (convertedBack); //prints 5

Observa, si sustituyes:

object convertedBack = Convert.ChangeType(o, type); Console.WriteLine (convertedBack); //it still prints 5 Console.WriteLine (o); //it even print 5 here

La razón es que el objeto subyacente sigue siendo int . Acabo de usar este ejemplo para mostrarte que el boxeo es irrelevante aquí. Debe confiar en alguna abstracción en sus operaciones y, si desea convertir dinámicamente a int , ¿qué tipo de referencia desea usar?


Aquí hay un ejemplo de exactamente por qué harías esto:

class MyClass { public int Id {get;set;} public string Name {get;set;} public decimal Val {get;set;} } int i = 0; var myClassImp = new MyClass(); foreach (var val in new [object]{"10", "My name", "100.21"} // Could be read from some data source, such as an excel spreadsheet { var prop = typeof(MyClass).GetProperties().ElementAt(i++); // !!!!!! THROWS EXCEPTION !!!!!!! prop.SetValue(myClassImp, System.Convert.ChangeType(val, prop.PropertyType), null); }

La razón de esto es porque el valor es un objeto encuadrado ... en el tiempo de ejecución, no conoce el tipo, por lo que tendría que desempaquetar el prop.PropertyType


En tales casos, voy a usar el patrón de estrategia usando un Dictionary<Type, Action<object>> :

internal class Program { private static void Main(string[] args) { var something = new Something(); something.ComputeValue(13); something.ComputeValue(DateTime.Now); something.ComputeValue(DayOfWeek.Monday); Console.ReadKey(); } } internal class Something { private static Dictionary<Type, Action<object>> _Strategies; static Something() { // Prepare all available strategies. _Strategies = new Dictionary<Type, Action<object>>(); _Strategies.Add(typeof(int), ComputeInteger); _Strategies.Add(typeof(DateTime), ComputeDateTime); } public void ComputeValue(object value) { Action<object> action; // Check if we have a matching strategy. if (!_Strategies.TryGetValue(value.GetType(), out action)) { // If not, log error, throw exception, whatever. action = LogUnknownType; } // Perform the matching strategy on the given value. action(value); } private static void ComputeDateTime(object source) { // We get an object, but we are sure that it will always be an DateTime. var value = (DateTime)source; Console.WriteLine("We''ve got an date time: " + value); } private static void ComputeInteger(object source) { // We get an object, but we are sure that it will always be an int. var value = (int)source; Console.WriteLine("We''ve got an integer: " + value); } private static void LogUnknownType(object source) { // What should we do with the drunken sailor? var unknownType = source.GetType(); Console.WriteLine("Don''t know how to handle " + unknownType.FullName); } }


Puedes intentar usar el runtime dinámico

[Test] public void Test_UnboxingAtRuntime() { object boxed = "Hello"; //this line is commented out as it does not compile // OverloadedMethod(boxed); var result = CallCorrectMethod(boxed); Assert.That(result, Is.EqualTo("string")); boxed = 1; result = CallCorrectMethod(boxed); Assert.That(result, Is.EqualTo("int")); } public string CallCorrectMethod(dynamic t) { return OverloadedMethod(t); } public string OverloadedMethod(string s) { return "string"; } public string OverloadedMethod(int s) { return "int"; }


Si no conoce el tipo en el momento de la compilación , no puede desempaquetar porque no tiene dónde colocarlo ; todo lo que puede hacer es almacenarlo en un object , que está: en caja.

Lo mismo se aplica a los tipos de referencia como string : no puede convertirlo al tipo correcto si no conoce el tipo en tiempo de compilación: no tiene dónde ponerlo .

Puede hacer un caso especial de algunos tipos, por ejemplo:

if(obj is int) { int i = (int)obj; ... } ...

Otro truco que a veces (no siempre) es útil es cambiar a los genéricos ; entonces, en lugar de hablar en términos de object , estás hablando en términos de T Esto tiene ... uso limitado sin embargo. La forma más fácil de hacerlo es a través de la dinámica , por ejemplo:

dynamic obj = ... Foo(obj); ... Foo<T>(T val) { ... code with T ... }

También puede agregar casos especiales a esa lista:

Foo(string val) { ... code with string ...} Foo(int val) { ... code with int ...}

Sin embargo, francamente sugiero que puede ser mejor mirar detenidamente lo que está tratando de hacer.


Una solución pragmática; intente y use un TypeConverter directamente, y si eso falla, conviértalo a cadena y viceversa: -

private static T GetValueOfType<T>(this ManagementBaseObject MBO, String FieldName) { T lResult; try { Object lObj = MBO[FieldName]; var lSrcType = lObj.GetType(); var lDestType = typeof(T); if (lDestType.IsValueType && lDestType.IsAssignableFrom(lSrcType)) { lResult = (T)lObj; return lResult; } var lDestTC = TypeDescriptor.GetConverter(typeof(T)); if (lDestTC.CanConvertFrom(lSrcType)) { lResult = (T)lDestTC.ConvertFrom(lObj); } else { var lSrcTC = TypeDescriptor.GetConverter(lSrcType); String lTmp = lSrcTC.ConvertToInvariantString(lObj); lResult = (T)lDestTC.ConvertFromInvariantString(lTmp); } } catch { lResult = default(T); } return lResult; }


Usa expresiones:

var y = DynamicCast (obj, desiredType);

static object DynamicCast(object source, Type type) { var parameter = Expression.Parameter(typeof(object), "input"); var cast = Expression.TypeAs(Expression.Convert(parameter, type), typeof(object)); var lambda = Expression.Lambda<Func<object, object>>(cast, parameter); var func = lambda.Compile(); return func(source); }


public static string GetType(object data) { Type type = data.GetType(); return Convert.ChangeType(data, type).GetType().Name; }

Hola, este método recibe datos de objeto y devuelve el nombre de tipo de cadena del objeto. Espero que esto sea lo que necesitas.