El siguiente código tiene un método estático, Foo()
, llamando a un método de instancia, Bar()
:
public sealed class Example
{
int count;
public static void Foo( dynamic x )
{
Bar(x);
}
void Bar( dynamic x )
{
count++;
}
}
Se compila sin errores * pero genera una excepción de enlace en tiempo de ejecución en tiempo de ejecución. La eliminación del parámetro dinámico de estos métodos provoca un error del compilador, como se esperaba.
Entonces, ¿por qué tener un parámetro dinámico permite compilar el código? ReSharper tampoco lo muestra como un error.
Edición 1: * en Visual Studio 2008
Edición 2: agregada sealed
ya que es posible que una subclase pueda contener un Bar(...)
método estático . Incluso la versión sellada se compila cuando no es posible que se pueda llamar a otro método que no sea el método de instancia en tiempo de ejecución.
c#
visual-studio-2008
dynamic
compiler-errors
Mike Scott
fuente
fuente
dynamic
menos que realmente lo necesite.Respuestas:
ACTUALIZACIÓN: la respuesta a continuación se escribió en 2012, antes de la introducción de C # 7.3 (mayo de 2018) . En Novedades de C # 7.3 , la sección Candidatos de sobrecarga mejorados , elemento 1, se explica cómo han cambiado las reglas de resolución de sobrecarga para que las sobrecargas no estáticas se descarten antes. Entonces, ¡la respuesta a continuación (y toda esta pregunta) tiene en su mayoría solo interés histórico por ahora!
(Pre C # 7.3 :)
Por alguna razón, la resolución de sobrecarga siempre encuentra la mejor coincidencia antes de buscar estática o no estática. Pruebe este código con todos los tipos estáticos:
Esto no se compilará porque la mejor sobrecarga es la que toma un archivo
string
. Pero bueno, ese es un método de instancia, así que el compilador se queja (en lugar de tomar la segunda mejor sobrecarga).Adición: Creo que la explicación del
dynamic
ejemplo de la pregunta original es que, para ser coherentes, cuando los tipos son dinámicos también encontramos primero la mejor sobrecarga (comprobando solo el número de parámetro y los tipos de parámetro, etc., no estático vs. -static), y solo entonces compruebe si hay estática. Pero eso significa que la verificación estática tiene que esperar hasta el tiempo de ejecución. De ahí el comportamiento observado.Adición tardía: algunos antecedentes sobre por qué eligieron hacer cosas en este orden divertido se pueden inferir de esta publicación de blog de Eric Lippert .
fuente
dynamic
se introdujo en el lenguaje, creo que los diseñadores de C # dijeron: "No consideraremos (2) el tiempo de compilación cuando sea unadynamic
expresión". Entonces, mi propósito aquí es tener una idea de por qué eligieron no verificar estático versus instancia hasta el tiempo de ejecución. Yo diría que esta verificación ocurre en el momento de la vinculación .Foo tiene un parámetro "x" que es dinámico, lo que significa que Bar (x) es una expresión dinámica.
Sería perfectamente posible que Example tuviera métodos como:
En cuyo caso se resolvería el método correcto, por lo que la declaración Bar (x) es perfectamente válida. El hecho de que exista un método de instancia Bar (x) es irrelevante y ni siquiera se considera: por definición , dado que Bar (x) es una expresión dinámica, hemos diferido la resolución al tiempo de ejecución.
fuente
La expresión "dinámica" se vinculará durante el tiempo de ejecución, por lo que si define un método estático con la firma correcta o un método de instancia, el compilador no lo comprobará.
El método "correcto" se determinará durante el tiempo de ejecución. El compilador no puede saber si hay un método válido allí durante el tiempo de ejecución.
La palabra clave "dinámica" se define para lenguajes dinámicos y de secuencia de comandos, donde el método se puede definir en cualquier momento, incluso durante el tiempo de ejecución. Cosas locas
Aquí, una muestra que maneja entradas pero no cadenas, debido al método, está en la instancia.
Puede agregar un método para manejar todas las llamadas "incorrectas", que no se pudieron manejar
fuente