2009-04-30 18 views
22

Ho il codice qui sotto:compilatore C#: non può accedere metodo statico in un contesto non-statico

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. 
    } 
} 

Il compilatore è molto arrabbiato ... Capisco il messaggio di errore, ma non so come risolvi questo. Stavo cercando di ottenere un tipo piuttosto che un oggetto per effettuare la chiamata al metodo statico, ma non trovo il modo di farlo correttamente. Inoltre questo si traduce in qualcosa di non elegante affatto.

Fondamentalmente, GenericBase è una classe da un framework con molti metodi statici e alcuni metodi di istanza. Il controller sta scrivendo questa classe e la estende.

Il contenitore è un gruppo di controller logici correlati.

Interessante: una versione Java di questo codice viene compilata correttamente, ma con un avviso. Anche l'esecuzione è corretta.

Esiste un modello di progettazione per risolvere questo?

Grazie per i vostri input!


Ho trovato un modo per sbarazzarsi di questo problema, grazie alle vostre risposte. Sembra funzionare, ma non so dirti se ci sono effetti collaterali.

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... 
} 

risposta

26

Una chiamata ad un metodo statico sarà compilato per chiamare un metodo statico specifico su una classe specifica. In altre parole, non utilizzerà il contenuto di B per determinare quale metodo statico chiamare.

Quindi la chiamata deve essere risolvibile in fase di compilazione, quindi si lamenta, perché per quanto ne sa, è possibile sostituire il contenuto di quella proprietà con più tipi concreti, il che significherebbe che la chiamata al metodo statico avrebbe da risolvere in un metodo statico in una di queste classi.

Il compilatore non ha nulla di simile a un metodo statico virtuale o astratto, quindi per uno non è possibile garantire che tutte quelle classi abbiano quel metodo statico. E dal momento che la chiamata deve essere risolvibile in fase di compilazione, non funzionerà in questo modo.

È possibile, come si è notato, chiamare un metodo di istanza dell'oggetto, che a sua volta chiama il metodo statico. Ciò non invalida le regole precedenti poiché quando il compilatore compila quel metodo di istanza, il metodo statico che chiamerà è costante e noto.

+0

Molto istruttivo, grazie!Leggendo le risposte di seguito, mi sto chiedendo una possibile soluzione. Sentiti libero di commentare. –

+0

dopo tutto, non si chiamano STATIC per niente – BlackTigerX

2

Non è possibile farlo in C#. Puoi farlo in VB.NET e Java, ma onestamente, non ha molto senso. Ti dà solo un falso senso del polimorfismo in un metodo static, che non è reale in alcun modo. Poiché non è polimorfico, l'intera chiamata al metodo è nota al momento della compilazione (staticamente) e potresti citare la chiamata direttamente con il nome della classe.

9

Per chiamare il metodo statico è necessario fare riferimento ad esso dalla classe in cui è definito, non un'istanza di quella classe.

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

Grazie! L'ho già notato. Sto cercando un modo per effettuare queste chiamate attraverso il contenitore. Cosa penseresti di ottenere prima la classe base su un'altra base che includerebbe chiamate di istanza a metodi statici, quindi da derivarne? –

1

Si può fare una di quelle:

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

Utilizzando l'istanza non è possibile, come già spiegato da altri.

+0

Grazie! L'ho già notato. Sto cercando un modo per effettuare queste chiamate attraverso il contenitore. Cosa penseresti di ottenere prima la classe base su un'altra base che includerebbe chiamate di istanza a metodi statici, quindi da derivarne? –

+0

Se pensi di aver "bisogno" di questa chiamata di istanza, aggiungi il tuo metodo proxy. Il mio consiglio è solo quello di cercare di mantenere l'API pulita e inequivocabile. – Lucero

+0

Dato che non posso chiamare direttamente membri statici usando la classe contenente, sembra che sia l'unica soluzione per ora. Accetto di mantenere l'API il più pulita possibile. –

Problemi correlati