2010-05-24 5 views
9

quiero hacer la siguienteDiseño de clase C#: ¿qué puedo usar en lugar de "resumen estático"? No

public abstract class MyAbstractClass 
{ 
    public static abstract int MagicId 
    { 
     get; 
    } 

    public static void DoSomeMagic() 
    { 
     // Need to get the MagicId value defined in the concrete implementation 
    } 
} 

public class MyConcreteClass : MyAbstractClass 
{ 
    public static override int MagicId 
    { 
     get { return 123; } 
    } 
} 

Sin embargo puedo porque se can't have static abstract members.

Entiendo por qué no puedo hacer esto, ¿alguna recomendación para un diseño que logre el mismo resultado?

(Para mayor claridad - Estoy tratando de proporcionar una biblioteca con una clase base abstracta pero las versiones concretas deben implementar ALGUNOS/métodos mismos y sí, hay buenas razones para mantenerla estática.)

+4

Me pregunto cuáles son las "buenas razones", ya que pueden influir en la mejor manera de proceder desde aquí. –

+0

Podría compartir las * buenas * razones para tener esta propiedad 'estática' para que podamos comprender mejor su situación y proponer soluciones. En este momento no está claro lo que estás tratando de lograr. –

+0

Realmente depende de lo que estás tratando de hacer. – bitbonk

Respuesta

4

¿Funcionaría el patrón Singleton quizás? Un enlace al artículo de MSDN que describe cómo implementar un conjunto unitario en C#:

http://msdn.microsoft.com/en-us/library/ff650316.aspx

En el ejemplo particular, la instancia Singelton podría extender una clase base abstracta con su MagicId en ella.

Es sólo una idea :)

5

Usted fundamentalmente no puede hacer que DoSomeMagic() trabaje con el diseño actual. Una llamada a MyConcreteClass.DoSomeMagic en el código fuente se traducirá a MyAbstractClasss.DoSomeMagic en IL. Se pierde el hecho de que originalmente se llamó usando MyConcreteClass.

Puede considerar tener una jerarquía de clases paralelas que tenga los mismos métodos que virtual - luego asocie cada instancia de la clase original con una instancia de la clase que contiene los miembros previamente estáticos ... y probablemente solo haya una instancia de cada uno de esos.

+0

Sí, entiendo por qué no puedo hacer lo anterior; mi pregunta es cuál es el diseño correcto. – Ryan

+2

@Ryan: Es por eso que también incluí el segundo párrafo :) –

0

No es un gran fan de esta opción, pero ...

Se podría declarar la propiedad estática, no es abstracto, virtual y lanzar una NotImplementedException que devuelve un mensaje de error que el método tiene que ser reemplaza en una clase derivada .

Mueve el error del tiempo de compilación al tiempo de ejecución, lo que es feo.

+0

No puede anular los miembros estáticos. – zneak

+0

Bah oops. Me gustaría menospreciarme si pudiera – JoshReedSchramm

2

Su mejor opción es utilizar una interfaz con MagicId sólo con un colocador

public interface IMagic 
{ 
    int MagicId { get; } 
} 

Por la naturaleza del significado estático sólo puede haber uno (sí, como Highlander) no se los puede sustituir.

El uso de una interfaz asume que su cliente implementará el contrato. Si quieren tener una instancia para cada uno o devolver el valor de una variable estática, depende de ellos.

La buena razón para mantener las cosas estáticas también significa que NO es necesario que se anule en la clase secundaria.

+2

+1 para la observación de Highlander – statenjason

+0

¿De qué manera el uso de interfaces me puede llevar más allá del resumen no estático? De hecho, es peor ya que el compilador no fuerza a la clase concreta a implementar la interfaz. http://stackoverflow.com/questions/510341/force-subclasses-of-an-interface-to-implement-tostring-c – Ryan

0

Los lenguajes que implementan la herencia de miembros estáticos lo hacen a través de metaclases (es decir, las clases también son objetos, y estos objetos tienen una metaclase, y existe una herencia estática a través de ella). Puedes transponerlo vagamente al patrón de fábrica: una clase tiene el miembro mágico y puede crear objetos de la segunda clase.

Eso, o usa la reflexión. Pero no puede garantizar, en tiempo de compilación, que una clase derivada implemente estáticamente una determinada propiedad.

0

¿Por qué no lo convierten en un miembro no estática?

+0

¿Qué miembro, o todos ellos? – Ryan

3

Me gustaría cuestionar que haya "buenas razones" para hacer que los miembros abstractos estén estáticos.

Si piensa que estos miembros pueden reflejar alguna propiedad de la propia clase derivada en lugar de una instancia determinada, esto no significa necesariamente que los miembros deben ser estáticos.

Considere la propiedad IList.IsFixedSize. Esto es realmente una propiedad del tipo de IList, no de ninguna instancia en particular (es decir, cualquier T[] va a ser de tamaño fijo, no va a variar de uno T[] a otro). Pero aún así debería ser un miembro de instancia. ¿Por qué? Porque desde múltiples tipos pueden implementar IList, variará de uno IList a otro.

Considere algún código que tome cualquier MyAbstractClass (de su ejemplo). Si este código se diseña correctamente, en la mayoría de los casos, no debería importar qué clase derivada está tratando realmente. Lo que importa es lo que expone MyAbstractClass. Si hace algún miembros abstractos estática, básicamente, la única manera de acceder a ellos serían así:

int magicId; 
if (concreteObject is MyConcreteClass) { 
    magicId = MyConcreteClass.MagicId; 
} else if (concreteObject is MyOtherConcreteClass) { 
    magicId = MyOtherConcreteClass.MagicId; 
} 

¿Por qué un desastre? Esto es mucho mejor, ¿verdad?

int magicId = concreteObject.MagicId; 

Pero quizás tienen otras buenas razones por las que no han ocurrido a mí.

0

El provider pattern, utilizado por el proveedor de membresía ASP.NET, por ejemplo, podría ser lo que está buscando.

No puede tener un comportamiento polimórfico en los miembros estáticos, por lo que tendrá una clase estática cuyos miembros delegan en un campo de interfaz (o clase abstracta) que encapsulará los comportamientos polimórficos.

Cuestiones relacionadas