2011-08-20 12 views
8

consideri il seguente codice:C#: Perché questo riferimento enum ambiguo non è stato risolto utilizzando la firma del metodo?

namespace ConsoleApplication 
{ 
    using NamespaceOne; 
    using NamespaceTwo; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      // Compilation error. MyEnum is an ambiguous reference 
      MethodNamespace.MethodClass.Frobble(MyEnum.foo); 
     } 
    } 
} 

namespace MethodNamespace 
{ 
    public static class MethodClass 
    { 
     public static void Frobble(NamespaceOne.MyEnum val) 
     { 
      System.Console.WriteLine("Frobbled a " + val.ToString()); 
     } 
    } 
} 

namespace NamespaceOne 
{ 
    public enum MyEnum 
    { 
     foo, bar, bat, baz 
    } 
} 

namespace NamespaceTwo 
{ 
    public enum MyEnum 
    { 
     foo, bar, bat, baz 
    } 
} 

Il compilatore segnala che MyEnum è un riferimento ambiguo nella chiamata a Frobble(). Poiché non vi è alcuna ambiguità in quale metodo viene chiamato, ci si potrebbe aspettare che il compilatore risolva il riferimento al tipo basato sulla firma del metodo. Perché no?

Si prega di notare che non sto dicendo che il compilatore dovrebbe fare questo. Sono fiducioso che ci sia una buona ragione che non sia così. Vorrei semplicemente sapere qual è questa ragione.

+0

Probabilmente vuole che il client sia sicuro che stia usando l'enum giusto dal giusto spazio dei nomi. – BoltClock

+0

hai inserito tutto questo codice nello stesso file? o hai un file per ogni spazio dei nomi? –

+0

@Juan Ayala: non importa; Sono sicuro che il compilatore è in disaccordo con l'uso di '' s' nello spazio dei nomi 'ConsoleApplication'. – BoltClock

risposta

13

Paul è corretta. Nella maggior parte delle situazioni in C# ragioniamo "dall'interno all'esterno".

non c'è ambiguità in quello che viene chiamato il metodo,

Che è inequivocabile a voi è irrilevante per il compilatore. Il compito della risoluzione di sovraccarico è determinare se il gruppo di metodi Frobble può essere risolto con un metodo specifico dato gli argomenti noti. Se non siamo in grado di determinare quali sono i tipi di argomento, non proviamo nemmeno a eseguire la risoluzione di sovraccarico.

I gruppi di metodi che contengono solo un metodo non sono speciali in questo senso. Dobbiamo ancora avere buoni argomenti prima che la risoluzione del sovraccarico possa avere successo.

Ci sono casi in cui ragioniamo da "esterno a dentro", vale a dire, quando si esegue l'analisi del tipo di lambda. Ciò rende l'algoritmo di risoluzione del sovraccarico estremamente complicato e fornisce al compilatore un problema da risolvere che è almeno NP-HARD in casi brutti. Ma nella maggior parte degli scenari vogliamo evitare questa complessità e spese; Le espressioni vengono analizzate analizzando le sottoespressioni secondarie prima dei loro genitori, non viceversa.

Più in generale: C# non è un "quando il programma è ambiguo utilizza l'euristica per fare ipotesi su ciò che il programmatore probabilmente intendeva" linguaggio. È un "informare lo sviluppatore che il loro programma non è chiaro e possibilmente rotto" linguaggio. Le parti del linguaggio che sono progettate per cercare di risolvere situazioni ambigue - come la risoluzione del sovraccarico o l'inferenza del tipo di metodo o gli array implicitamente tipizzati - sono attentamente progettate in modo che gli algoritmi abbiano regole chiare che tengano conto della versione e di altri aspetti del mondo reale . Salvagare non appena una parte del programma è ambigua è un modo per raggiungere questo obiettivo progettuale.

Se si preferisce un linguaggio più "indulgente" che cerca di capire cosa intendi, VB o JScript potrebbero essere lingue migliori per te. Sono più lingue "fai quello che intendevo non quello che ho detto".

+5

È facile essere corretti quando tutto ciò che si deve fare è collegarsi a uno dei tuoi fantastici articoli del blog :) –

1

NamespaceOne e Namespace Due sono definiti nello stesso file di codice. Ciò equivarrebbe a metterli in file di codice diversi e a farvi riferimento tramite l'istruzione.

In tal caso è possibile capire perché i nomi si scontrano. Avete ugualmente chiamato enum in due differenti namesapce e il compilatore non può indovinare quale sia, anche se Frobble ha un parametro NamespaceOne.MyEnum. Invece di

MethodNamespace.MethodClass.Frobble(MyEnum.foo) 

uso

MethodNamespace.MethodClass.Frobble(NamespaceOne.MyEnum.foo) 
+0

Probabilmente è così semplice come si ottiene. – BoltClock

+0

Non sono stato confuso su come risolvere l'ambiguità. Ero curioso di sapere perché la firma del metodo non fosse usata per risolvere il tipo di argomento in questo caso. Ora so che è indietro - i tipi di argomenti sono risolti prima del metodo. – Odrade

Problemi correlati