2009-05-05 13 views
36

Recientemente me encontré con un problema donde parece que necesito un método de 'resumen estático'. Sé por qué es imposible, pero ¿cómo puedo evitar esta limitación?C#, implementar 'resumen estático' como métodos

Por ejemplo, tengo una clase abstracta que tiene una cadena de descripción. Desde esta cadena es común para todos los casos, se marca como algo estático, pero quiero exigir que todas las clases derivadas de esta clase proporcionan su propio Descripción propiedad, así que marqué como resumen:

abstract class AbstractBase 
{ 
    ... 
    public static abstract string Description{get;} 
    ... 
} 

No lo hará compilar por supuesto. Pensé en usar interfaces, pero las interfaces pueden no contener firmas de métodos estáticos.

¿Debo hacerlo simplemente no estático, y siempre obtener una instancia para conseguir que la información específica de clase?

¿Alguna idea?

+0

Similar a esta pregunta http://stackoverflow.com/questions/763344/c-virtual-or-abstract-static-methods/763364#763364 –

+0

Posible duplicado de [¿Por qué no puedo tener métodos estáticos abstractos en C# ?] (https://stackoverflow.com/questions/3284/why-cant-i-have-abstract-static-methods-in-c) –

+0

Posible duplicado de [¿Cómo implementar propiedades estáticas virtuales?] (https://stackoverflow.com/questions/15346631/how-to-implement-virtual-static-properties) – peterh

Respuesta

5

Combinando estático y abstracto es algo sin sentido, sí. La idea detrás de la estática es que no es necesario presentar una instancia de la clase para usar el miembro en cuestión; sin embargo, con el resumen, uno espera que una instancia sea de una clase derivada que proporciona una implementación concreta.

puedo ver por qué te gustaría este tipo de combinación, pero el hecho es el único efecto sería negar el uso de la aplicación 'esto' o algún miembro no estáticas. Es decir, la clase padre dictaría una restricción en la implementación de la clase derivada, aunque no haya una diferencia subyacente entre llamar a un miembro abstracto o 'resumen estático' (ya que ambos necesitarían una instancia concreta para descubrir qué implementación usar)

+0

Pensé que la situación otra vez, y digo que eso es cierto ... cadena pública abstracta {get;} implementada como cadena pública {get {return "Izeeeeeeeeh";}} es suficiente para una clase específica. – Calmarius

+71

No tiene sentido. Imagina que estás diseñando un marco. Necesita que las clases que implementan ISomething expongan algunos datos conocidos en tiempo de compilación. Por ejemplo, un "nombre de clase amigable". Desea que el compilador se asegure de que todos los ISomethings tengan esta propiedad. Si quieres hacer eso ahora, entonces tienes que usar propiedades de instancia. Lo que significa crear una instancia, en lugar de solo consultar el tipo. Eso apesta. –

+3

Estoy de acuerdo con @RyanBarrett, para el diseño del marco puede ser útil forzar a un consumidor a proporcionar una función en una clase derivada, pero también establece contractualmente que la función se ejecuta estáticamente, sin que haya una instancia. –

31

Usted no puede.

El lugar de hacerlo es con atributos.

Ej

[Name("FooClass")] 
class Foo 
{ 
} 
+0

Inteligente. . . – Shog9

+3

De hecho ... uno podría tener la propiedad de Descripción estática pública recoger el valor del atributo para hacerlo más accesible ... –

+0

Estaría interesado en saber cómo funciona eso en tiempo de ejecución. ¿El atributo termina como una instancia var de alguna manera? He leído atributos personalizados antes a través de la reflexión, pero no sé cómo los maneja CLR –

3

No es estática si tiene que ser llamado en una instancia.

Si no lo está llamando en una instancia, entonces no hay polimorfismo en juego (es decir, ChildA.Description no está relacionado con ChildB.Description en lo que respecta al lenguaje).

5

Si es estático, solo hay una instancia de la variable, no veo cómo la herencia tendría sentido si pudiéramos hacer lo que queremos lograr con variables estáticas en las clases derivadas. Personalmente, creo que vas a intentar evitar una instancia var.

Por qué no sólo la manera clásica?

abstract class AbstractBase 
{ 
    protected string _Description = "I am boring abstract default value"; 
} 

class Foo : AbstractBase { 

    public Foo() { 
     _Description = "I am foo!"; 
    } 
} 
5

Si no le importa aplazar hasta implementaciones para implementar sensiblemente la propiedad Description, sólo tiene que hacer

public abstract string ClassDescription {get; } 
// ClassDescription is more intention-revealing than Description 

Y las clases que implementan haría algo como esto:

static string classDescription="My Description for this class"; 
override string ClassDescription { get { return classDescription; } } 

Luego, se requiere que sus clases sigan el contrato de tener una descripción, pero usted les deja hacerlo con sensatez. No hay forma de especificar una implementación de forma orientada a objetos (excepto a través de hacks crueles y frágiles).

Sin embargo, en mi opinión esta descripción es metadatos de clase, por lo que preferiría utilizar el mecanismo de atributo como otros han descrito. Si está particularmente preocupado por los múltiples usos de la reflexión, cree un objeto que refleje sobre el atributo que le preocupa y almacene un diccionario entre el Tipo y la Descripción. Eso minimizará la reflexión (aparte de la inspección de tipo de tiempo de ejecución, que no es del todo mala). El diccionario se puede almacenar como miembro de cualquier clase que normalmente necesite esta información o, si los clientes de todo el dominio lo requieren, a través de un objeto singleton o de contexto.

0

Puede hacer que el método base "abstracto" arroje un Exception, entonces un desarrollador es "advertido" si intenta invocar este método en una clase secundaria sin anular.

El inconveniente es que uno podría extender la clase y no usar este método. Luego consulte otras respuestas proporcionadas.

Cuestiones relacionadas