2012-01-31 10 views
5

Ok, una pregunta fácil.¿Evaluar en captador de propiedades o al crear una instancia?

Antes que nada, debo decir que mi preocupación no es rendimiento. Soy totalmente consciente de que cualquier costo de rendimiento que una u otra opción impliquen probablemente carezca de sentido y ni siquiera valga la pena considerarlo en los escenarios normales. Tiene más que ver con los estándares de diseño y la curiosidad sobre cómo lo haría la mayoría de los codificadores.

Ok, así que la pregunta es bastante simple:

Supongamos que tengo un ComplexNumberstruct que podría poner en práctica la siguiente manera:

public struct Complex : IEquatable<Complex>, IFormattable 
{ 
    readonly double realPart, imaginaryPart, magnitude, argument; 
    readonly static Complex j = new Complex(0, 1); 

    public Complex(double realPart, double imaginaryPart) 
    { 
     this.realPart = realPart; 
     this.imaginaryPart = imaginaryPart; 
     this.magnitude = Math.Sqrt(Math.Pow(realPart, 2) + Math.Pow(imaginaryPart, 2)); 
     this.argument = Math.Atan2(imaginaryPart, realPart); 
    } 

    public double RealPart { get { return this.realPart; } } 
    public double ImaginaryPart { get { return this.imaginaryPart; } } 
    public double Magnitude { get { return this.magnitude; } } 
    public double Argument { get { return this.argument; } } 

    public static Complex J { get { return Complex.j; } } 
    ... 
} 

Los Magnitude y Argument propiedades tienen un respaldo campos que se encuentran evaluado en tiempo de construcción. Otra opción sería simplemente evaluar el valor correspondiente en cualquier getter.

¿Cuál es la forma más recomendable de hacerlo? ¿Existe algún estándar de codificación que recomiende alguna opción por el solo hecho de tener un estándar? Y si no hay uno, ¿cuál es normalmente la opción preferida? ¿O depende solo del rendimiento, que en mi caso es irrelevante?

Respuesta

1

[ACTUALIZADO A CONTINUACIÓN:]

¿Por qué evaluar en el captador y no en la incubadora? Evaluaría el valor tal como se establece. De esta forma, el valor correcto se puede usar en métodos privados.

Establecer valores predeterminados en c'tor, evaluar en setter.

Siempre leerá el valor con más frecuencia que al establecerlo, por lo que, por motivos de rendimiento, debe hacer la evaluación en el colocador; se ejecutará con menos frecuencia.

[ACTUALIZACIÓN:] Si la propiedad es de solo lectura, evalúe en el administrador, por el mismo razonamiento que el anterior (rendimiento: solo hará la evaluación una vez). Sé que dices que el rendimiento no es un problema, pero si no hay motivos para no hacerlo de la mejor manera, debería hacerlo así.

+2

Ehm, no hay setters en el código. – svick

+1

No te sigo. Este es un tipo inmutable, no hay setters. La pregunta es si elegir la opción de inicializar los campos correspondientes en el constructor y luego hacerlos disponibles a través de un getter o simplemente elegir no tener campo de respaldo y evaluar cada vez en el getter. – InBetween

+0

Por supuesto, actualizado anteriormente – hofnarwillie

0

C'tor debe inicializar los miembros con valores predeterminados.

Definitivamente, el rendimiento puede ser un problema si mueve el código a getter porque evaluará cada vez que se invoca getter.

Sin embargo, el contrato de getter dice que obtendrá el valor. por lo que la parte de cálculo debe evitarse tanto como sea posible en el bloque getter.

Y también debe tratar de evitar el uso de valores sucios. si configura el Magnitude (por ejemplo) en getter, pero intente acceder a él dentro de la clase directamente; podrías terminar usando el valor equivocado.

Por lo tanto, si la pregunta es sobre la iniciación de las variables miembro, hágalo en c'tor. es por eso que es creado por diseñadores de idiomas.

+0

La pregunta no es sobre la inicialización de las variables miembro. Esa pregunta es discutible cuando se trata de * tipos de valores *, ya que es * obligatorio * para hacerlo. La pregunta es si vale la pena tener las variables miembro para comenzar. – InBetween

+2

No estoy de acuerdo con que se evite el cálculo en getters. Especialmente si es un código relativamente simple como aquí. – svick

+0

@InBetween: Sí, si la memoria no es un problema. será más escalable a medida que cambien los requisitos. – Azodious

1

Yo preferiría calcular los valores directamente en getters, porque es más legible: si quieres saber qué hace Argument, solo mira su código. Si almacenó en caché el valor en un campo como el que tiene ahora, debe ir a la propiedad Argumentargument campo → constructor.

Si el rendimiento sí importó, obviamente la forma correcta de averiguar qué opción es mejor en su caso es la creación de perfiles. Pero como , supongo que, creo que la versión con valores en caché en los campos también será más lenta, especialmente si no usas los valores calculados con frecuencia. Esto se debe a que struct s se copian todo el tiempo y esos campos hacen que el struct sea el doble de grande.

+0

El código legible siempre es una ventaja, y sí, hacer que los captadores hagan el trabajo hace que el código sea más fácil de leer y descubrir lo que está haciendo con un simple vistazo. Por supuesto, en un tipo tan simple, esto podría ser un factor menor, pero aún debe tenerse en cuenta. – InBetween

+0

@svick: si solo se considera este código, poner código en getter está bien. pero considerándolo como regla general, no lo preferiré. – Azodious

Cuestiones relacionadas