2008-10-01 14 views
47

Tengo una clase con una interfaz estática y una no estática en C#. ¿Es posible tener un método estático y no estático en una clase con el mismo nombre y firma?Métodos estáticos y de instancia con el mismo nombre?

Aparece un error de compilación cuando trato de hacer esto, pero por alguna razón pensé que había una manera de hacerlo. ¿Estoy equivocado o no hay forma de tener métodos estáticos y no estáticos en la misma clase?

Si esto no es posible, ¿hay una buena manera de implementar algo como esto que se pueda aplicar genéricamente a cualquier situación?

EDITAR
partir de las respuestas que he recibido, está claro que no hay manera de hacer esto. Voy con un sistema de nombres diferente para evitar este problema.

+0

¿Puede darnos un ejemplo de dónde podría querer hacer esto? –

+1

No recomiendo que confíe en las diferencias entre mayúsculas y minúsculas para distinguir dos métodos. Muy mala idea. Nunca debe tener dos métodos que difieren solo en el caso: le garantizo que terminará llamando a la incorrecta. –

+3

Cambie el nombre de los métodos a diferentes nombres. Confiar en el caso no es seguro, especialmente si existe la posibilidad de que el código compilado sea utilizado por otro lenguaje .NET que no distinga entre mayúsculas y minúsculas. Solo porque el idioma distinga entre mayúsculas y minúsculas, debe confiar en ese hecho para eliminar la ambigüedad de los nombres de los métodos. –

Respuesta

52

No, no puedes. El motivo de la limitación es que los métodos estáticos también se pueden invocar desde contextos no estáticos sin necesidad de anteponer el nombre de la clase (así que MyStaticMethod() en lugar de MyClass.MyStaticMethod()). El compilador no puede decir qué estás buscando si tienes ambos.

Puede tener métodos estáticos y no estáticos con el mismo nombre, pero diferentes parámetros que siguen las mismas reglas que la sobrecarga de métodos, simplemente no pueden tener exactamente la misma firma.

+17

La lógica de esta respuesta me parece errónea. No veo ninguna razón por la cual C# no pudo realizar la desambiguación requiriendo el "esto". token para llamar al método de instancia en esta situación. Además, andasa muestra una forma en que los métodos estáticos y de instancia pueden tener el mismo nombre. – mheyman

+3

Es cierto que probablemente podrían hacer algún tipo de comprobación que seleccionaría el método estático por defecto si hubiera una colisión y lo requeriría. para acceder a los métodos de instancia. Por supuesto, eso sería complicado cuando se trata de propiedades estáticas, ya que dentro del alcance de un método si sus parámetros fueron nombrados igual que una de sus propiedades estáticas/de instancia, entonces tendría que usar el nombre de clase para especificar la versión estática, esto para especificar la versión de la instancia y, si no hay nada, acceder al parámetro. Parece una excelente manera de obtener muchos errores difíciles de encontrar para mí. – ckramer

+2

Creo que todas las llamadas desde un ámbito no estático deberían realizarse por defecto al método no estático. Si desea el global, debe solicitarlo prefijando el nombre de la clase. –

11

Usted puede llamar a métodos estáticos de los métodos de instancia sin tener que especificar el nombre del tipo:

class Foo 
{ 
    static void Bar() 
    { 
    } 

    void Fizz() 
    { 
     Bar(); 
    } 
} 

... así que tiene sentido que no se le permitiría tener un método estático y un método de instancia con la misma firma

¿Qué estás tratando de lograr? Es difícil sugerir una solución alternativa sin conocer los detalles. Solo cambiaría el nombre a uno de los métodos.

0

Puede tener métodos estáticos y de instancia con el mismo nombre, siempre que su declaración difiera en el número o tipo de parámetros. Es la misma regla sobre cómo puede tener dos métodos de instancia con el mismo nombre en una clase.

Aunque técnicamente, en el caso de método estático frente a instancia, ya difieren por la presencia del parámetro implícito en el método de instancia, esa diferencia no es suficiente para que el compilador determine cuál de los dos desea llamada.

Actualización: He cometido un error. Los valores de devolución no son suficientes para tener una firma diferente.

+0

Incorrecto: siempre que difieran en el número y/o tipo de parámetros. Los tipos de devolución no se sobrecargan. – asterite

+0

[suspiro] sí, tienes razón ... –

36

En realidad, hay una manera de lograr esto mediante la implementación explícita de una interfaz. No es una solución perfecta, pero puede funcionar en algunos casos.

interface IFoo 
{ 
    void Bar(); 
} 

class Foo : IFoo 
{ 
    static void Bar() 
    { 
    } 

    void IFoo.Bar() 
    { 
     Bar(); 
    } 
} 

a veces me encuentro con esta situación cuando hago clases de envoltura para P/Invoke llamadas.

+0

Mi razonamiento exacto para hacer esto fue P/Invoke Calls. Gracias :) – Asheh

+0

Acabo de arreglar eso, @Kamarey. La implementación explícita de la interfaz no debe tener modificadores de acceso, siempre es pública. – Palec

-1

OK. El origen de este problema es que C# no debería permitirle llamar a un método estático desde un método de instancia sin especificar el nombre del tipo.

Otros lenguajes completos de OO (como Smalltalk) no permiten esto y también es una confusión para las personas que entienden los objetos. La separación entre el lado de la instancia y el lado de la clase (o estática) es muy importante y tener un lenguaje que promueva confusión en esos detalles es ........ no una buena idea ... pero típico del tipo de cosas que esperar de MS.

Adrian

+0

Tu publicación no responde la pregunta. Considere agregar una respuesta específica a la pregunta o agregue un comentario para una explicación de la pregunta. –

+1

Entiendo los votos abajo porque no responde la pregunta, pero esta es realmente la causa del problema. Tiene más sentido para un desarrollador ver el nombre de clase antes que un método estático como un indicador de primera vista que "Sí, este es un método estático, propiedad, campo", etc. – Brandon

+1

Tres años después, pero quiero Por ejemplo, agradezco los puntos que hizo Adriana, pero no las declaraciones peyorativas de la pareja que fueron totalmente fuera de base, particularmente: "C# no debería dejar que llames", "pero es típico del tipo de cosas que esperamos de MS". Sin embargo, el primer punto es una opinión FINA que se debe mantener, pero no se debe mencionar como una cuestión de hecho. –

3

C# no está bien diseñado, cuando se trata de esto ...

Si bien es cierto que lo que pueda desear lo global o no global, debe escoger uno por defecto, y si quieres el otro, entonces simplemente lo calificas más.

class Logger { 
    public static Logger instance; 

    public static void Log(string message) { 
     instance.Log(message); // currently the compiler thinks this is ambiguous, but really its not at all. Clearly we want the non-static method 
    } 

    public void Log(string message) { 

    } 

    public void DoStuff() { 
     Log("doing instance stuff"); // this could be ambiguous, but in my opinion it should default to a call to this.Log() 
     Logger.Log("doing global stuff"); // if you want the global qualify it explicitly 
    } 
} 
Cuestiones relacionadas