2009-05-20 21 views
8

Tengo una pregunta que no es realmente un problema, pero algo que me hizo un poco de curiosidad.Pregunta sobre llamadas ambiguas en C#

Tengo una clase con dos métodos en ella. Uno es un método estático y el otro es un método de instancia. Los métodos tienen el mismo nombre.

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

Cuando intento para construir mi proyecto me da un error diciendo:

La llamada es ambigua entre las siguientes métodos o propiedades: 'MyApp.BlockHeader.Peek (System.IO. BinaryReader)' y 'MyApp.BlockHeader.Peek (System.IO.BinaryReader)'

sé que las firmas de los métodos son vir Tually lo mismo, pero no veo cómo podría llamar a un método estático directamente desde un miembro de instancia.

Supongo que hay una muy buena razón para esto, pero ¿alguien sabe cuál es esa razón?

+3

Creo que esto se debe a que J # y otros lenguajes le permiten llamar a métodos estáticos de los miembros de la instancia. El CLR tiene que hacer cumplir el denominador común más bajo. –

+0

No sabía que J # lo permitía. Interesante. – Patrik

+4

Esto me parece extraño también. La especificación es extremadamente clara de que este comportamiento es _correcto_. Ver la Sección 7.5.5.1, el bit que dice: "Si el mejor método es un método estático, el grupo de métodos debe ser el resultado de un nombre simple o un acceso de miembro a través de un tipo ..." Observe cómo sucede ese bit DESPUÉS del bit donde descubrir el "mejor" método. La "bondad" se calcula claramente PRIMERO, antes de verificar la estática. Por lo tanto, la bondad no tiene en cuenta la estática, y en su caso, no se puede determinar el mejor método. Por lo tanto, error de ambigüedad –

Respuesta

9

La política general del diseño de C# es forzarlo a especificar donde haya una posible ambigüedad. Frente a las herramientas de refactorización que nos permiten replantear si las cosas son estáticas o no en un abrir y cerrar de ojos, esta postura es excelente, especialmente en casos como este. Verá muchos otros casos como este (reemplazo frente a virtual, nuevo para sombreado, etc.).

En general, quitar este tipo de espacio por confusión hará que el código sea más claro y lo obliga a mantener su casa en orden.

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

+7

El ejemplo clásico (en este caso) es un método de instancia que llama Peek (...); es eso esto. ¿Peek? o BlockHeader.Peek? –

+0

Veo tu punto. – Patrik

+0

1k, bien hecho, puedes comprarme una pinta por la tarde –

2

Creo que no hay ninguna razón técnica para no permitir que, pero se hace más que para proteger el programador de sí mismo. Consideremos el siguiente ejemplo:

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

El ejemplo anterior es perfectamente válido, pero si la situación que describes se permitiera, sería legible? ¿Podría ver, en un abrir y cerrar de ojos, si se llamó al método de instancia o al método estático?

+0

Veo tu punto. Buen ejemplo – Patrik

4

Aquí hay un extracto de la especificación del lenguaje C# 3.0.

La firma de un método debe ser única en la clase en la que se declara el método. La firma de un método consiste en el nombre del método, el número de parámetros de tipo y el número, modificadores y tipos de sus parámetros. La firma de un método no incluye el tipo de devolución.

El modificador "estático" no es parte de la firma, por lo que su ejemplo infringe esta regla de firmas únicas.

No sé la razón detrás de la regla, sin embargo.