2011-09-13 38 views
7

Necesito una forma de crear una clase estática donde algunas constantes pueden ser específicas de un caso, pero codificadas.clase abstracta estática

Lo que realmente quiero hacer es tener una clase donde se proporcionen varias constantes cuando se amplíe la clase. Quiero que las 'constantes' estén codificadas. Pensé que haría algunas propiedades abstractas y definiría el get {return constant; } al extender la clase.

Sé que no es posible, por lo que ahora estoy frente a dos opciones y me pregunto qué es lo mejor y por qué (si hay opciones que me faltan por favor hágamelo saber!)

  1. Crear una clase estática con campos anulables y lanzar una excepción si los campos son nulos cuando se llama al método estático.
  2. Renunciar a la clase estática. Tener una clase no estática con propiedades abstractas y crear una instancia del objeto donde sea que lo necesite aunque toda la funcionalidad sea realmente estática.

Sé que esto podría ser subjetivo y depende de cada caso, sin embargo estoy dando vueltas en círculos al pensar en esto y podría realmente hacer con alguna entrada externa. Eso más, espero que haya algo de lo que quiero y simplemente estoy pensando en esto.

Actualización: Código: Intentaré escribir un código que describa lo que me gustaría lograr. ¡Sé que este código no puede funcionar!

Imagine que la clase abstracta Cálculo está en una DLL, utilizada por muchos proyectos. La funcionalidad es la misma para todos ellos, solo la constante varía de un proyecto a otro.

public abstract static class Calculation 
{ 
    private abstract int Constant { get; } //The constant is unknown at this time 

    public static int Calculate(int inputValue) 
    { 
     return inputValue * Constant; 
    } 
} 

La clase Calc se define en un proyecto separado donde se necesita la funcionalidad y se conoce la constante.

public static class Calc : Calculation 
{ 
    private override int Constant { get { return 2; } 
} 

... 

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     //At some point: 
     int result = Calc.Calculate(6); 
    } 
} 

supongo que la forma más sencilla sería la creación de una clase no estática y crear una instancia, sin embargo, me temo que tienen varias instancias de la clase podrían ser costosos y me gustaría evitar que si es posible.

No puedo ver cómo podría escribir esto como un patrón singleton sin escribirlo nuevamente en cada proyecto - teniendo solo la clase anidada en la dll. Eso no impide que el implementador simplemente cree una clase ordinaria y es probable que reinicie el debate para cada proyecto donde se usa el código.

Actualización # 2: Lo que ment con la opción uno es la siguiente:

clase en un DLL:

public static class Calculation 
{ 
    public int? Constant {get; set;} 

    public static int Calculate(int inputValue) 
    { 
     if (Constant == null) 
      throw new ArgumentNullException(); 

     return inputValue * (int)Constant; 
    } 
} 

Uso de la función en un proyecto independiente:

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     //At some point: 
     Calculation.Constant = 2; 
     int result = Calc.Calculate(6); 
    } 
} 

La opción uno es muy simple y elegante, lo que me molesta es que nada fuerza el implementador para establecer la constante. Me temo que un escenario (por cierto improbable) donde un caso de esquina oscuro hará que no se establezca la propiedad y que el código falle (y que Constant sea el último sospechoso) ...

+0

¿Por qué cree que necesita una clase estática? ¿Y a qué te refieres con "caso específico, pero codificado"? ¿Podrías publicar un ejemplo concreto? – svick

+0

No puede extender (heredar) una clase estática, entonces, ¿cuál es exactamente su escenario? Un pequeño fragmento de código vale 1000 palabras. –

+0

¿Puede describir el uso de algún código de muestra, posiblemente no compilable? –

Respuesta

6

Puede crear clases no estáticas que sigan singleton, asegurando que solo exista una instancia del objeto. Supongo que podría ser la segunda mejor opción.

+1

No veo cómo ayuda el singleton en este caso.La pregunta es sobre herencia (no es un punto fuerte de singletons) y propiedades estáticas. –

+0

Comentario de [Anne Lagang] (http://stackoverflow.com/users/906815/anne-lagang): "Si necesita ayuda con Singleton, consulte [Singleton] de Jon Skeet (http://csharpindepth.com/Articles/ General/Singleton.aspx) artículo ". –

5

¡No puede desear la estática y la herencia al mismo tiempo! ¡Simplemente tiene sentido!

¡Si necesita anular el comportamiento, necesita herencia!

Si desea simplicidad de llamada (una de las ventajas de la estática), se puede utilizar de fábrica (o Singleton si se necesita sólo un ejemplo)

Mi conjetura es que es probable que tenga que replantearse su modelo. Este conjunto de constantes tuyas probablemente represente algo que puedas extraer en una clase separada y luego pasar esta clase a tu método estático. ¿Eso se adaptaría a tus necesidades?

1

Editar

Para el ejemplo de código:

public abstract static class Calculation 
{ 
    public static int Constant { get; set; } 
    public static int Calculate(int i) { return i * Constant; } 
} 

// ... 

Calculation.Constant = 6; 
Calculation.Calculate(123); 

algo más general:

public abstract static class Calculation 
{ 
    public struct Context 
    { 
     public int Constant, SignificantDigits; 
     public bool Radians; 
    } 
    public static int Calculate(int i, Context ctx) { return i * ctx.Constant; } 
} 

// ... 
Calculation.Calculate(123, new Calculate.Context { Constant = 6 }); 

primera idea:

El más cercano que puedo pensar es en los genéricos:

public interface ISpecifics 
{ 
    void DoSomething(); 
    string SomeProp { get; } 
} 

public static class Static<S> 
    where S : ISpecifics, new() 
{ 

     public static string ExerciseSpecific() 
     { 
      var spec = new S(); 
      spec.DoSomething(); 
      return spec.SomeProp; 
     } 
} 

O si realmente necesita un solo tipo estático

public static class Static 
{ 
     public static string ExerciseSpecific<S>() 
      where S : ISpecifics, new() 
     { 
      var spec = new S(); 
      spec.DoSomething(); 
      return spec.SomeProp; 
     } 
} 

ayuda eso?

+0

Para su edición: Eso es lo que menciono en la opción 1. en mi pregunta original. ¿Tiene la propiedad ser int? Constant {get; set;} y en Calculate (int inputValue) {if (Constant == null) throw new NullArgumentException(); return inputValue * (int) Constante; } –

+0

@David: Creo que todavía estaba en edición. Mira mi respuesta ahora (Puede usar 'int '' donde digo 'int' si es más apropiado) – sehe

+0

¿el tipo actual no sería int ?. Probablemente será byte [], el punto que estaba tratando de hacer es que puede ser nulo y eso indicará un error. La opción más general con Context no funciona para mí. Lea la línea inferior de mi pregunta para ver por qué no quiero usar esta opción. –

0

Necesitaba más o menos lo mismo, así que primero hice una clase no estática con todas las funcionalidades. Luego, una clase estática que ejemplifica una clase no estática en su constructor estático. Luego, cualquiera de los métodos estáticos llama a los métodos de instancia respectivos.

Algo como esto:

public class CalculationInstance 
{ 
    private int constant; 

    public int Calculate(int inputValue) 
    { 
     return inputValue * constant; 
    } 

    public void AnyOtherMethod() 
    { 
    .... 
    }  

    public CalculationInstance(int constant) 
    { 
    this.constant=constant;  
    } 
} 


public static class Calculation 
{ 
    const int CONSTANT=2; 
    private CalculationInstance calc; 

    static Calculation() 
    { 
     calc=new CalculationInstance(CONSTANT); 
    } 

    public static int Calculate(int inputValue) 
    { 
     return calc.Calculate(inputValue); 
    } 

    public static void AnyOtherMethod() 
    { 
     calc.AnyOtherMethod(); 
    }  

} 

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     //At some point: 
     int result = Calculation.Calculate(6); 
    } 
}