una - metodo public static c#
¿Por qué el compilador de C#no falla el código donde un método estático llama a un método de instancia? (3)
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 error * pero genera una excepción de encuadernador de tiempo de ejecución en tiempo de ejecución. La eliminación del parámetro dinámico de estos métodos provoca un error de compilación, como se esperaba.
Entonces, ¿por qué tener un parámetro dinámico permite que se compile el código? ReSharper tampoco lo muestra como un error.
Editar 1: * en Visual Studio 2008
Editar 2: se agregó sealed
ya que es posible que una subclase contenga un método Bar(...)
estático. Incluso la versión sellada se compila cuando no es posible llamar a otro método que no sea el método de instancia en tiempo de ejecució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 el Ejemplo tenga métodos como:
static Bar(SomeType obj)
En ese caso, se resolvería el método correcto, por lo que la declaración Bar (x) es perfectamente válida. El hecho de que haya un método de instancia Bar (x) es irrelevante e incluso no considerado: por definición , dado que Bar (x) es una expresión dinámica, hemos diferido la resolución al tiempo de ejecución.
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 verificará.
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 los lenguajes dinámicos y de script, donde el Método se puede definir en cualquier momento, incluso durante el tiempo de ejecución. Cosas locas
Aquí hay una muestra que maneja los enteros pero no las cadenas, porque el método está en la instancia.
class Program {
static void Main(string[] args) {
Example.Foo(1234);
Example.Foo("1234");
}
}
public class Example {
int count;
public static void Foo(dynamic x) {
Bar(x);
}
public static void Bar(int a) {
Console.WriteLine(a);
}
void Bar(dynamic x) {
count++;
}
}
Puede agregar un método para manejar todas las llamadas "incorrectas", que no se pudieron manejar
public class Example {
int count;
public static void Foo(dynamic x) {
Bar(x);
}
public static void Bar<T>(T a) {
Console.WriteLine("Error handling:" + a);
}
public static void Bar(int a) {
Console.WriteLine(a);
}
void Bar(dynamic x) {
count++;
}
}
Por alguna razón, la resolución de sobrecarga siempre encuentra la mejor coincidencia antes de buscar estática frente a no estática. Por favor intente este código con todos los tipos estáticos:
class SillyStuff
{
static void SameName(object o) { }
void SameName(string s) { }
public static void Test()
{
SameName("Hi mom");
}
}
Esto no compilará porque la mejor sobrecarga es la que toma una string
. Pero bueno, ese es un método de instancia, por lo que el compilador se queja (en lugar de tomar la segunda mejor sobrecarga).
Además: Creo que la explicación del ejemplo dynamic
de la pregunta original es que, para ser consistentes, cuando los tipos son dinámicos, también encontramos la mejor sobrecarga (verificando solo el número de parámetro y los tipos de parámetros, etc., no estático vs. no estático), y solo luego verifica si estático. Pero eso significa que la comprobación estática debe esperar hasta el tiempo de ejecución. De ahí el comportamiento observado.
Adición tardía: algunos antecedentes sobre por qué eligieron hacer las cosas, esta divertida orden puede deducirse de esta publicación del blog de Eric Lippert .