2011-08-20 17 views
8

considere el siguiente código:C#: ¿Por qué no se resuelve esta referencia de enumeración ambigua utilizando la firma del método?

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

El compilador se queja de que MyEnum es una referencia ambigua en la llamada a Frobble(). Dado que no existe ambigüedad en el método que se está llamando, se puede esperar que el compilador resuelva la referencia de tipo en función de la firma del método. ¿Por qué no?

Tenga en cuenta que no estoy diciendo que el compilador debería hacer esto. Estoy seguro de que hay una muy buena razón para que no sea así. Simplemente me gustaría saber cuál es esa razón.

+0

Probablemente quiere que el cliente esté seguro de que está usando la enumeración correcta del espacio de nombres correcto. – BoltClock

+0

pones todo este código en el mismo archivo? o tienes un archivo para cada espacio de nombres? –

+0

@Juan Ayala: No importa; Estoy seguro de que el compilador solo tiene problemas con 'using's en el espacio de nombres' ConsoleApplication'. – BoltClock

Respuesta

13

Paul es correcta. En la mayoría de las situaciones en C# razonamos "de adentro hacia afuera".

no hay ambigüedad en qué método se está llamando,

Eso es inequívoca a que es irrelevante para el compilador. La tarea de la resolución de sobrecarga es determinar si el grupo de métodos Frobble se puede resolver con un método específico teniendo en cuenta los argumentos conocidos. Si no podemos determinar cuáles son los tipos de argumento, entonces ni siquiera intentamos hacer una resolución de sobrecarga.

Los grupos de métodos que simplemente contienen un único método no son especiales a este respecto. Todavía tenemos que tener buenos argumentos antes de que la resolución de sobrecarga pueda tener éxito.

Hay casos en los que razonamos de "afuera hacia adentro", es decir, al hacer un análisis de tipo de lambdas. Hacerlo hace que el algoritmo de resolución de sobrecarga sea extremadamente complicado y le da al compilador un problema para resolver que es al menos NP-HARD en casos malos. Pero en la mayoría de los escenarios queremos evitar esa complejidad y gasto; las expresiones se analizan mediante el análisis de las subexpresiones secundarias antes de sus padres, y no al revés.

Más en general: C# no es un "cuando el programa es ambiguo usa heurística para hacer conjeturas sobre lo que el programador probablemente quiso decir" lenguaje. Es un "informar al desarrollador que su programa no está claro y posiblemente roto". Las partes del lenguaje que están diseñadas para tratar de resolver situaciones ambiguas, como resolución de sobrecarga o inferencia de tipo de método o matrices implícitamente tipadas, están cuidadosamente diseñadas para que los algoritmos tengan reglas claras que tengan en cuenta el control de versiones y otros aspectos del mundo real. . Rescatar tan pronto como una parte del programa sea ambigua es una forma de lograr este objetivo de diseño.

Si prefiere un lenguaje más "tolerante" que intente entender lo que usted quiso decir, VB o JScript podrían ser mejores idiomas para usted. Son más los idiomas "haz lo que quise decir no lo que dije".

+5

Es fácil estar en lo correcto cuando todo lo que uno tiene que hacer es enlazar a uno de sus increíbles artículos de blog :) –

1

Namespace One y Namespace Two se definen en el mismo archivo de código. Eso sería equivalente a ponerlos en diferentes archivos de código y hacer referencia a ellos mediante el uso de la declaración.

En ese caso, puede ver por qué los nombres chocan. Igualmente ha llamado a enum en dos nombres diferentes y el compilador no puede adivinar de cuál se trata, aunque Frobble tiene un parámetro NamespaceOne.MyEnum. En lugar de

MethodNamespace.MethodClass.Frobble(MyEnum.foo) 

uso

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

Esto es probablemente tan simple como se pone. – BoltClock

+0

No estoy confundido acerca de cómo resolver la ambigüedad. Tenía curiosidad sobre por qué la firma del método no se usó para resolver el tipo de argumento en este caso. Ahora sé que está al revés: los tipos de argumentos se resuelven antes que el método. – Odrade

Cuestiones relacionadas