2009-05-20 20 views
8

Ho una domanda che non è davvero un problema, ma qualcosa che mi ha reso un po 'curioso.Domanda su chiamate ambigue in C#

Ho una classe con due metodi. Uno è un metodo statico e l'altro è un metodo di istanza. I metodi hanno lo stesso nome.

public class BlockHeader 
{ 
    public static BlockHeader Peek(BinaryReader reader) 
    { 
     // Create a block header and peek at it.   
     BlockHeader blockHeader = new BlockHeader(); 
     blockHeader.Peek(reader); 
     return blockHeader; 
    } 

    public virtual void Peek(BinaryReader reader) 
    { 
     // Do magic. 
    } 
} 

Quando si tenta di costruire il mio progetto ho un errore che dice:

La chiamata è ambigua tra le seguenti metodi o proprietà: 'MyApp.BlockHeader.Peek (System.IO. BinaryReader)' e 'MyApp.BlockHeader.Peek (System.IO.BinaryReader)'

so che le firme dei metodi sono vir lo stesso, ma non riesco a vedere come potrei chiamare un metodo statico direttamente da un membro di istanza.

Suppongo che ci sia una buona ragione per questo, ma qualcuno sa qual è questa ragione?

+3

Penso che ciò sia dovuto al fatto che J # e altri linguaggi consentono di chiamare metodi statici dai membri dell'istanza. Il CLR deve far rispettare il minimo comune denominatore. –

+0

Non sapevo che J # permettesse questo. Interessante. – Patrik

+4

Trovo questo bizzarro pure. La specifica è estremamente chiara che questo comportamento è _correct_. Vedere la sezione 7.5.5.1, il bit che va: "Se il metodo migliore è un metodo statico, il gruppo metodo deve essere il risultato di un nome semplice o di un accesso membro attraverso un tipo ..." Si noti come quel bit accade dopo il bit dove capire il metodo "migliore". "Bestness" è chiaramente calcolato PRIMA, prima di verificare la staticità. Quindi la bontà non tiene conto della staticità e nel tuo caso non è possibile determinare il metodo migliore. Pertanto, errore di ambiguità. –

risposta

9

La politica generale del design C# è di costringerti a specificare ovunque ci sia una potenziale ambiguità. Di fronte a strumenti di refactoring che consentono di regiungere se le cose sono statiche o meno alla caduta di un cappello, questa posizione è ottima - specialmente per casi come questo. Vedrai molti altri casi come questo (override vs virtual, new for shadowing, ecc.).

In generale, rimuovere questo tipo di spazio per la confusione renderà il codice più chiaro e ti costringerà a mantenere la tua casa in ordine.

EDIT: A good post from Eric Lippert discusses another reason for this ambiguity leading to the error you saw

+7

L'esempio classico (in questo caso) è un metodo di istanza che chiama Peek (...); è questo? o BlockHeader.Peek? –

+0

Vedo il tuo punto. – Patrik

+0

1k, ben fatto, puoi comprarmi pinta qualche sera –

2

Penso che ci sia alcuna ragione tecnica per non consentire esso, ma è fatto di più per proteggere il programmatore da se stesso. Si consideri il seguente esempio:

public static void Main() 
{ 
    BlockHeader BlockHeader = new BlockHeader(); 
    BlockHeader.Peek(); 
} 

L'esempio precedente è perfettamente valido, ma se la situazione che lei descrive è stato permesso, sarebbe leggibile? Potresti vedere, in un batter d'occhio, se è stato chiamato il metodo di istanza o il metodo statico?

+0

Vedo il tuo punto. Grande esempio. – Patrik

4

Ecco un estratto dalle specifiche del linguaggio C# 3.0.

La firma di un metodo deve essere univoca nella classe in cui è dichiarato il metodo. La firma di un metodo è costituita dal nome del metodo, dal numero di parametri del tipo e dal numero, dai modificatori e dai tipi dei suoi parametri. La firma di un metodo non include il tipo di reso.

Il modificatore "statico" non fa parte della firma, pertanto il tuo esempio viola questa regola delle firme uniche.

Non conosco il motivo alla base della regola, però.