2009-12-01 14 views
7

Digamos que tiene una clase con 300 propiedades sin variables de respaldo, cada una de esas propiedades devuelve un decimal/doble.Propiedad C#, ¿es posible evitar la definición de obtención sin definir conjunto (sin variable de respaldo)?

Ejemplo:

public decimal MathValue { get; set; } 

Ahora se decidió que cada uno de esos valores deben redondearse.

Estoy buscando la forma más sencilla de refactorizar esto sin tener que reescribir todas esas propiedades.

Algo, de este modo equivalente que realmente funciona: D:

public decimal MathValue { get {return Math.Round(MathValue);} set; } 
+0

Es posible que desee pensar en volver a esta clase después y volver factorizando algunas propiedades en buenas clases de limpieza para que pueda evitar ese desorden. – ChaosPandion

+0

lol, completa la exageración de mi parte. Tenía curiosidad de cómo alguien puede evitarlo :) – Andrew

Respuesta

5

Puede crear un nuevo tipo de valor que simule ser un decimal, pero devuelve el valor redondeado. Algo como esto:

struct RoundedDecimal 
{ 
    public decimal Value { get; private set; } 

    public RoundedDecimal(decimal value) : this() 
    { 
     this.Value = value; 
    } 

    public static implicit operator decimal(RoundedDecimal d) 
    { 
     return Math.Round(d.Value); 
    } 
} 

Cada propiedad en su clase debe ser de tipo RoundedDecimal en lugar de decimal.

+0

Llamaría a esto 'Int96', porque eso es lo que efectivamente es. –

+0

Esta es una gran manera de llevarlo a cabo sin romper la interfaz. – ChaosPandion

+0

En realidad, probablemente sería mejor si creó un campo público de solo lectura llamado Value y lo redondea en el constructor. – ChaosPandion

6

No. Si usted necesita toda la lógica propia, ya sea en getter o setter, no se puede utilizar auto-propiedades.

+0

¿Y no hay forma de anular esta lógica o solución al respecto sin declarar una variable para cada uno? – Andrew

+0

Una alternativa sería escribir una línea de comando util (o preferiblemente utilizar T4) para generar sus 300 propiedades para usted a partir de algún otro archivo/datos. – ConsultUtah

+0

Puede usar algo como PostSharp para reescribir sus propiedades después de la compilación. Sin embargo, probablemente no valga la pena por algo tan trivial como eso. –

0

Pero, ¿qué sucede si el cliente no quiere un valor redondeado? es decir, ¿algún nuevo código de cliente establece un decimal y espera que ese valor "exacto" vuelva?

Si algunos clientes realmente necesitan que se redondee la salida de la llamada de propiedad, entonces el cliente debe manejar esto y dejar su clase solo.

+0

Bueno, entonces en ese caso el get puede quedar solo :) para esa propiedad en particular ... lo único que quiero hacer es evitar declarar una variable para cada propiedad. – Andrew

1

Puede crear una derivada de esta clase que anule la obtención y devuelva los valores redondeados. Entonces necesitaría modificar la propiedad base para que sea virtual. Pero eso le permitiría definir el get sin definir el conjunto y usar propiedades automáticas.

public class Base 
{ 
    public virtual decimal MathValue { get; set; } 
} 

public class Derived : Base 
{ 
    public override decimal MathValue 
    { 
     get { return Math.Round(base.MathValue); } 
    } 
} 
+0

¿Cómo se podría lograr esto? Me gustaría anular los get ellos mismos, si eso es posible. ¿Podrías quizás mostrarme un ejemplo? – Andrew

+0

Claro. También aclaré que toda la propiedad debe ser virtual, no solo el captador. –

+0

La herencia parece excesiva para esto. – ChaosPandion

0

Visual Studio solía tener un "prop" fragmento de código incorporado que generaría algo así como el código siguiente:

private decimal _MathValue; 

    public decimal MathValue 
    { 
     get { return _MathValue; } 
     set { _MathValue = value; } 
    } 

Eso ayudaría a que la mayor parte del camino a una solución completa, pero desde VS 2008 se genera ahora la versión automática de la propiedad:

public decimal MathValue { get; set; } 

no he probado esto todavía, pero here is a suggestion for creating your own code snippet to get the VS 2005 version of the "prop" code snippet back:

+0

Estoy más interesado en una forma de evitar el código en lugar de refaccionar manualmente todo en la clase, incluso si tengo un fragmento que lo hace por mí. – Andrew

+0

Ah, sí, debería haber leído su pregunta más de cerca. Veo que se encuentra en una situación en la que ya tiene cientos de propiedades definidas, por lo que realmente no lo ayuda mucho. –

+0

:) gracias por ayudar – Andrew

0

Una opción es usar programación orientada a aspectos para interceptar las invocaciones de propiedad al retorno y redondear el valor de retorno antes de pasar el control nuevamente al llamador.

4

¿La forma más fácil de refactorizar el código? Esto es lo que haría:

  1. abierto Notepad ++ (conseguirlo si no lo tiene)
  2. Copia/pega todas las propiedades de la clase en un área de texto en blanco.
  3. Coloque el cursor al comienzo de la primera línea: decimal público MathValue1 {get; conjunto; }
  4. Comience a grabar una macro (haga clic en el botón grabar en la barra de herramientas)
  5. mantenga presionada la flecha hacia la derecha (llamada "palabra correcta") 3 veces para poner el cursor al comienzo del nombre de la propiedad.
  6. hacer Shift + Ctrl + Flecha derecha 1 vez y hacer una copia de poner el nombre de la propiedad en el portapapeles
  7. palabra correcta 3 veces más para poner el cursor después del "obtener"
  8. eliminar la semi dos puntos después de la tipificación llegar y empezar a "{return Math.Round (_"
  9. hacer una pasta 10 tipo ");}"
  10. palabra derecha 2 veces más para poner el cursor después del "set"
  11. elimine el punto y coma después del conjunto y comience a escribir "{_"
  12. haga una Pegar
  13. type "= value; }
  14. presione la tecla Finalizar para colocar el cursor al final de la línea
  15. presione la tecla de la flecha hacia la derecha para colocar el cursor al comienzo de la siguiente línea.
  16. presione el botón de detener para finalizar su macro (botón cuadrado en la barra de herramientas)
  17. Haga clic en el botón "Ejecutar una macro varias veces" (un ícono de doble flecha en la barra de herramientas) y diga "Ejecutar hasta el final del archivo" "
  18. Copie/pegue el texto resultante en su clase para reemplazar las definiciones de propiedad originales.

Ahora deberá definir un conjunto de variables privadas correspondientes que comiencen con un guión bajo pero que, por lo demás, tengan los mismos nombres que las propiedades. Comience con una copia nueva de las propiedades de su clase y realice un conjunto de pasos similares a los descritos anteriormente.

Mi hipótesis es que cada línea comienza con 2 pestañas y no hay líneas vacías entre las propiedades.

En lugar de tener cada propiedad llamada Math.Round, es posible que desee considerar la definición de su propia función de utilidad a la que todos llaman, de modo que si necesita cambiarla nuevamente, puede simplemente cambiarla en un solo lugar.

+0

+1 - Nunca hubiera pensado en esto. Es posible que desee presionar ctrl-k-d antes de hacerlo, así que VS limpiará todo el espacio en blanco. – ChaosPandion

0

Puede hacer esto con PostSharp o algún otro framework AOP basado en .NET. Aquí está el MethodExecutionEventArgs.ReturnValue property que dice que se puede utilizar para "modificar el valor de retorno ..."

Esto lo hará:

[Serializable] 
public class RoundingAttribute : OnMethodBoundaryAspect 
{ 
    public override void OnExit(MethodExecutionEventArgs eventArgs) 
    { 
     base.OnExit(eventArgs); 
     eventArgs.ReturnValue = Math.Round((double)eventArgs.ReturnValue, 2); 
    } 
} 

class MyClass 
{ 
    public double NotRounded { get; set; } 

    public double Rounded { [Rounding] get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var c = new MyClass 
       { 
        Rounded = 1.99999, 
        NotRounded = 1.99999 
       }; 

     Console.WriteLine("Rounded = {0}", c.Rounded); // Writes 2 
     Console.WriteLine("Not Rounded = {0}", c.NotRounded); // Writes 1.99999 
    } 
} 
Cuestiones relacionadas