2009-06-23 20 views
6

Cómo convertir un objeto (de tipo Objeto) en su tipo real?¿Cómo convertir un objeto en su tipo?

tengo que hacer algo como este tipo

Myobject [i] += Myobject [j]; 

de MyObject es objeto. Myobject [i] y myobject [j] siempre serán del mismo tipo.

MyObject [i] .Gettype() me daría el tipo ... pero ¿Cómo puedo convertir el objeto en realidad en ese tipo para llevar a cabo el signo '+' operador

+0

¿Cómo se declara la matriz de Myobject? – ChrisF

+0

¿Está definido el operador '+' para el tipo de 'MyObject'? – Groo

+0

objeto [] Myobject –

Respuesta

16

Asumo la adición (+) operador se define para su tipo personalizado (MyType en este ejemplo).

En caso afirmativo, solo tiene que emitir el LHS y el RHS de la tarea. Esto es necesario porque ambos operandos deben ser de tipos conocidos en tiempo de compilación para elegir la sobrecarga correcta del operador. Esto es algo requerido por los lenguajes estáticos, aunque los lenguajes dinámicos (posiblemente C# 4.0) pueden resolver esto.

((MyType)Myobject[i]) += (MyType)Myobject[j]; 

Actualización:

un poco de magia reflexión puede solucionar este problema en C# 2.0/3.0 (con falta de tipado dinámico).

public static object Add(object a, object b) 
{ 
    var type = a.GetType(); 
    if (type != b.GetType()) 
     throw new ArgumentException("Operands are not of the same type."); 

    var op = type.GetMethod("op_Addition", BindingFlags.Static | BindingFlags.Public); 
    return op.Invoke(null, new object[] { a, b }); 
} 

Tenga en cuenta que esto sólo funciona para tipos no primitivos. Para tipos primitivos como int, float, etc., necesitaría agregar una declaración de interruptor en el tipo que emite manualmente los operandos y aplica el operador de suma. Esto se debe a que las sobrecargas del operador no están realmente definidas para los tipos primitivos, sino que están integradas en el CLR.

De todos modos, espero que resuelva su problema.

+0

No sé el tipo de "MyType" en tiempo de compilación –

+1

Hmmm, eso complica las cosas ... – Noldorin

+0

Ver mi respuesta actualizada, y también los comentarios de Marc sobre su publicación. – Noldorin

1

Si Myobject es una matriz entonces

Myobject [i] += Myobject [j]; 

debería funcionar siempre que el operador + se ha definido para el tipo.

Como Myobject es de tipo de objeto esta fallará con el error:

Operator '+' cannot be applied to operands of type 'object' and 'object'

para obtener el tipo en tiempo de ejecución (un ejemplo artificial):

double a = 1.0; 
double b = 2.0; 

object a1 = a; 
object b1 = b; 

Type ta = a1.GetType(); 
Type tb = b1.GetType(); 

ta y tb están ajustados a " Doble".

ACTUALIZACIÓN:

Una palabra de advertencia por adelantado - lo que voy a sugerir es muy torpe (por decir lo menos)

Si usted tiene un número finito de tipos y son los tipos garantizado para ser el mismoSi es así, puede hacer lo siguiente:

Type test = Myobject[i].GetType(); 
if (test.Equals(typeof(double))) 
{ 
    (double)Myobject[i] += (double)Myobject[j]; 
} 

y así sucesivamente.

Si los tipos no son iguales, es un poco más complicado.

Si usted tiene un número desconocido de tipos, entonces tendrá que esperar para C# 4.

O usted podría hacer con la reflexión como sugiere noldorin.

8

¿Es el tipo conocido en tiempo de compilación?

C# no admite (hasta C# 4.0) operadores en nada excepto en tipos fijos conocidos.

Puede usar operadores con genéricos mediante algunos trucos - like so. Déjeme saber si los genéricos son un factor aquí (se puede hablar largo y tendido sobre esto ...)

En 4.0, puede utilizar:

dynamic x = MyObject[i]; 
x += MyObject[j]; 
MyObject[i] = x; 

El uso de dynamic provoca mucha magia a suceder ;-p

Aparte de esos dos escenarios, necesita saber su tipo en tiempo de compilación, o hacer un lote de trabajo.

+0

La magia es lo que mantiene al mundo girando. –

+0

Tipo sería un tipo numérico. podría ser flotante, doble, entero o cualquier cosa –

+0

Lo cual no cambia nada, desafortunadamente. El truco de los "genéricos" es probablemente la mejor opción, pero eso requiere una matriz de tipos. Puede usar MakeGenericMethod para cambiar de 'objeto' al código de operador genérico, pero no será bonito. Y MakeGenericMethod es lento ('dynamic' sería mejor, cuando se libera). –

0

Siempre es mejor evitar el boxeo y el desempaquetado y usar tipos directos. No conozco todos sus antecedentes, pero tal vez sea mejor cambiar la matriz al tipo real o usar una lista genérica.

MyType[] array = new MyType[x]; 

o

List<MyType> list = new List<MyType>(); 
0

voy a sugerir el uso de una declaración Swicth, como el tipo sería uno numérico. En cada rama, que pudieras jugar sus números para las variables temporales y realizar la operación como:

switch (Myobjetc[j].GetType()) 
    { 
     case typeof(short):     
      break; 
     case typeof(int): 
      int a, b = 0; 
      a = (int)Myobjet[i]; 
      b = (int)Myobject[j]; 
      a += b; 
      break; 
     case typeof(long): 
      break; 
     case typeof(decimal): 
      break; 
     case typeof(double): 
      break; 
     case typeof(float): 
      break;    
     default: 
      break; 
    } 
+2

Excepto que el interruptor (obj.GetType()) no compila - "Un valor de tipo integral" esperado " – ChrisF

+0

reemplazando 'cambiar' por 'if' haría ... requiere algún trabajo (y prueba) aunque –

+0

obj.GetType() se refiere a Myobject [j]/Myobject [i], era solo para escribir un poco más rápido. Voy a editar ahora mismo. –

0

Una mejor solución para los tipos primitivos que no requiere una instrucción switch es así: (VB.Net)

Private Shared AddT As Func(Of T, T, T) 
If AddT = Nothing Then 
    Dim paramX As Expressions.ParameterExpression = Expressions.Expression.Parameter(GetType(T), "x") 
    Dim paramY As Expressions.ParameterExpression = Expressions.Expression.Parameter(GetType(T), "y") 
    Dim body As Expressions.BinaryExpression = Expressions.Expression.AddChecked(paramX, paramY) 
    Matrix(Of T).AddT = Expressions.Expression.Lambda(Of Func(Of T, T, T))(body, paramX, paramY).Compile 
End If 
Private a as MyType 
Private b as MyType 
AddT(a,b) 'instead of a+b 

Las soluciones para multiplicar, dividir, etc. son similares. ¡Con suerte, convertir lo anterior a C# no será demasiado doloroso! Es importante que AddT se comparta (estática) porque recompilar la expresión lambda perderá ciclos de reloj cada vez. Es una lástima .Net no tiene un "MyType implementa {+, -, *, etc}"!

Cuestiones relacionadas