2009-04-30 10 views
22

tengo el código de abajo:compilador de C#: no se puede acceder método estático en un contexto no estático

public class Anything 
{ 
    public int Data { get; set;} 
} 

public class MyGenericBase<T> 
{ 
    public void InstanceMethod(T data) 
    { 
     // do some job 
    } 

    public static void StaticMethod(T data) 
    { 
     // do some job 
    } 

    // others members... 
} 

public sealed class UsefulController : MyGenericBase<Anything> 
{ 
    public void ProxyToStaticMethod() 
    { 
     StaticMethod(null); 
    } 

    // others non derived members... 
} 

public class Container 
{ 
    public UsefulController B { get; set; } 
} 

public class Demo 
{ 
    public static void Test() 
    { 
     var c = new Container(); 
     c.B.InstanceMethod(null); // Works as expected. 
     c.B.StaticMethod(null);  // Doesn't work. 
            // Static method call on object rather than type. 
            // How to get the static method on the base type ? 
     c.B.ProxyToStaticMethod(); // Works as expected. 
    } 
} 

el compilador está muy enojado ... entiendo el mensaje de error, pero no sé cómo resuelve esto. Estaba intentando obtener un tipo en lugar de un objeto para hacer mi llamada al método estático, pero no encuentro la manera de hacerlo correctamente. Además, esto da como resultado algo no elegante en absoluto.

Básicamente, GenericBase es una clase de un framework con muchos métodos estáticos y algunos métodos de instancia. El controlador está escribiendo esta clase y ampliándola.

El contenedor es un grupo de controladores lógicos relacionados.

Una cosa interesante: una versión de Java de este código se compila correctamente, pero con una advertencia. La ejecución es correcta también.

¿Existe un patrón de diseño para resolver esto?

Gracias por sus entradas!


He encontrado la manera de deshacerte de este problema, gracias a tus respuestas. Parece que funciona, pero no puedo decir si hay efectos secundarios.

public class GenericBase<T> : MyGenericBase<T> 
{ 
    // Create instance calls here for every base static method. 
} 

public sealed class UsefulController : GenericBase<Anything> 
{ 
    // others non derived members... 
} 

Respuesta

26

Se compilará una llamada a un método estático para llamar a un método estático específico en una clase específica. En otras palabras, no usará el contenido de B para determinar qué método estático llamar.

Entonces la llamada tiene que resolverse en tiempo de compilación, por lo que se queja, porque por lo que sabe, podría reemplazar el contenido de esa propiedad por varios tipos concretos, lo que significaría que la llamada al método estático para ser resuelto a un método estático en cualquiera de estas clases.

El compilador no tiene nada que ver con un método estático virtual o abstracto, por lo que no se puede garantizar que todas esas clases tengan ese método estático. Y dado que la llamada debe resolverse en tiempo de compilación, no funcionará así.

Puede, como habrá notado, llamar a un método de instancia del objeto, que a su vez llama al método estático. Esto no invalida las reglas anteriores ya que cuando el compilador compila ese método de instancia, el método estático al que llamará es constante y conocido.

+0

Muy instructivo, gracias!Leyendo las respuestas a continuación, me pregunto acerca de una posible solución. Siéntete libre de comentar –

+0

después de todo, no se llaman STATIC por nada – BlackTigerX

2

No puede hacer esto en C#. Puedes hacerlo en VB.NET y Java, pero sinceramente, no tiene sentido. Simplemente te da una falsa sensación de polimorfismo en un método static, que no es real de ninguna manera. Como no es polimórfico, toda la llamada al método se conoce en tiempo de compilación (estáticamente) y puede mencionar la llamada directamente con el nombre de la clase.

9

Para llamar al método estático, debe consultarlo desde la clase en la que está definido, no una instancia de esa clase.

MyGenericBase<Anything>.StaticMethod(null); 
+0

¡Gracias! Ya noté esto. Estoy buscando una forma de hacer estas llamadas a través del contenedor. ¿Qué le parecería derivar primero la clase base a otra base que incluiría llamadas de instancia a métodos estáticos, y luego derivar de ella? –

1

Usted puede hacer uno de esos:

UsefulController.StaticMethod(null); 
MyGenericBase<Anything>.StaticMethod(null); 

El uso de la instancia no es posible, como ya se ha explicado por otros.

+0

Gracias! Ya noté esto. Estoy buscando una forma de hacer estas llamadas a través del contenedor. ¿Qué le parecería derivar primero la clase base a otra base que incluiría llamadas de instancia a métodos estáticos, y luego derivar de ella? –

+0

Si crees que "necesitas" esta llamada de instancia, simplemente agrega tu método proxy. Mi consejo es solo tratar de mantener la API limpia y sin ambigüedades. – Lucero

+0

Como no puedo llamar directamente a los miembros estáticos que usan la clase contenedora, parece que es la única solución por ahora. Acepto mantener la API lo más limpia posible. –

Cuestiones relacionadas