2012-05-04 27 views
8

I tienen esta función:Operador con C# dinámico?

static void Func1<T>(T x, T y) 
{ 
    dynamic result = ((dynamic)x + y); //line 1 
    dynamic result2 = (x + y);   //line 2 
} 

Esta func puede ser ejecutado como Func(1,2); Sin embargo, la línea 1 es OK, mientras que la línea 2 va BANG (en tiempo de compilación).

La excepción lanzada de la línea 2 es:

operador '+' no se puede aplicar a operandos de tipo 'T' y 'T'

Por lo tanto, tenemos que crear un operador sobrecarga. Bien, hasta ahora todo bien.

Pero, ¿qué pasa con la línea 1? ¿No debería necesitar un molde dinámico también en y?

((dynamic)x + (dynamic)y);

entiendo que está siendo evaluado en tiempo de ejecución, pero ¿por qué acepto el compilador de C# + el operador en la línea 1 (es decir erróneamente asumen que T puede ser + a otra cosa)?

+0

¿Cuál es el valor en 'resultado' después de ejecutar el código? ¿Es '3' o '12'? Supongo que está haciendo concatenación de cadenas. – Servy

+1

@Servy: ¿Qué te hace pensar que haría una concatenación de cadenas cuando 'T' es' int'? – LukeH

Respuesta

7

En su primer ejemplo, al hacer x a dynamic, en realidad ha hecho que la operación operator+ también sea dinámica. Esto elimina el especificador de tipo T para x, eliminando así la queja de que T no tiene operator+ válido.

En tiempo de ejecución dinámica ocurrirá y evaluar los dos operandos para asegurar que operator+ puede utilizarse la unión:

Si un operando de un operador aritmético tiene el tipo en tiempo de compilación dinámica, entonces la expresión está vinculado dinámicamente (§7.2.2). En este caso, el tipo de expresión en tiempo de compilación es dinámico, y la resolución que se describe a continuación se llevará a cabo en tiempo de ejecución utilizando el tipo de tiempo de ejecución de los operandos que tienen el tipo dinámico de tiempo de compilación.

En el segundo ejemplo, el compilador conoce los tipos de x + y y es simplemente almacenando el resultado en una variable dynamic. Otros usos de result2 se vincularán dinámicamente.Esto tiene sentido ya que no existen operaciones dinámicas a la derecho del operador de asignación:

Cuando no hay expresiones dinámicas están involucrados, C# por defecto a la unión estática, lo que significa que los tipos de tiempo de compilación de expresiones constitutivas son utilizado en el proceso de selección.

+0

Además, tengo que preguntarme por qué haría un método genérico intente utilizar operadores específicos de tipo sin una restricción. – Tejs

+0

Bueno, para algo como tipos numéricos no se puede encontrar ninguna restricción de tipo que permita operaciones aritméticas. – user7116

+0

Creo que la forma preferida sería simplemente hacer sobrecargas para esos tipos de valores específicos como lo hace el framework. De lo contrario, si desea que tipos específicos realicen algún tipo de operación como esa, haga que implementen una interfaz específica y luego restrinja esa interfaz. – Tejs

3

dynamic básicamente le dice al compilador "no intentes asegurarte de que lo que estoy haciendo sea legal; estoy seguro de que será en tiempo de ejecución". Se compilará cualquier operación que intente en una variable de tipo dinámico. Simplemente no se ejecutará correctamente si el tipo asignado a la variable dinámica no implementa realmente la operación.

En cuanto a por qué ambos no tienen que ser dinámicos, el compilador básicamente intentará encontrar un operador (método estático) en cualquiera de los tipos implicados en la operación que coincida con la firma, comenzando con LValue. Con LValue siendo dinámico, el compilador debe suponer que la operación existe en cualquier cosa que se use como X, aunque X tiene el mismo tipo de marcador de posición que Y y no se sabe que tenga un operador +.