2010-09-15 9 views
7

¿Hay alguna forma en C# para marcar una propiedad como determinista?Determinismo de propiedad

La razón por la que pregunto es que a menudo me encuentro a mí mismo declarando una variable local y leyendo una propiedad en ella, en lugar de acceder a la propiedad varias veces.

¿Hay alguna manera de que pueda decorar la propiedad como determinista, de modo que el compilador pueda entonces optimizar los accesos múltiples a esa propiedad? Estoy adivinando en tal escenario que la clase tendría que ser inmutable y decorada como tal.

¿Esto es algo que incluso existe o estoy agarrándome a las pajas?

Respuesta

7

Si la propiedad es simple, como una propiedad implícita:

public int X { get; set; } 

o la lectura de una variable local:

public int X { get { return _x; } } 

entonces el compilador optimizará el código de modo que no hay diferencia entre acceder a la propiedad varias veces y poner la propiedad en una variable y acceder a eso.

Comprobé esto comparando 100 millones de iteraciones de acceso a una propiedad diez veces y copiando la propiedad a una variable y accediendo a esa diez veces, y no hay ninguna diferencia mensurable en absoluto.

En general, las propiedades deben ser leight-weight, para que no tenga que esperar ningún procesamiento pesado cada vez que acceda a ellas.Si el valor de la propiedad es costoso de obtener, la clase debe almacenar en caché el valor internamente de modo que la lectura de la propiedad solo haga que la operación sea costosa la primera vez (patrón de carga diferida).

Si una propiedad es costosa de obtener cada vez, no debe ser una propiedad en absoluto, sino un método getter.

+0

+1 - Solo una pregunta: si el compilador realiza esta optimización de todos modos, ¿cómo podría explicar los cambios en el objeto en objetos no inmutables, ya sea que provenga del mismo hilo o no? ¿Es posible que hayas validado que la propiedad tiene un costo de propiedad simple en una cantidad muy pequeña, en cuyo caso debería dejar de ser anal al respecto? :) –

+0

@Matt Whitfield: Cuando se optimiza el código, la propiedad simple será internada. Leer la propiedad en realidad no llamará a un comprador de propiedades para devolver el valor, sino que obtendrá el valor directamente, como si estuviera accediendo a una variable pública en la clase. En el código C# obtienes la abstracción y el aislamiento que deseas en el código OOP, pero en el código compilado obtienes la velocidad de las variables públicas. :) – Guffa

+0

gracias - Voy a aceptar esto porque ese comentario que tienes es el que me da el entendimiento que estaba buscando cuando hice la pregunta. –

0

A menos que el campo de respaldo de su propiedad sea readonly, ¿cómo va a explicar los problemas de enhebrado?

5

No hay ningún mecanismo en C# que le permita introducir getters de propiedades const, es decir, getters que no cambian el estado del objeto.

La documentación de Microsoft se limita a recomendar not to introduce any side-effects en sus captadores:

Es un mal estilo de programación para cambiar el estado del objeto mediante el acceso get. Por ejemplo, el siguiente descriptor de acceso produce el efecto secundario de cambiar el estado del objeto cada vez que se accede al campo numérico.

private int number; 
public int Number 
{ 
    get 
    { 
     return number++; // Don't do this 
    } 
} 

Como se ha mencionado por Daren, otro aspecto a considerar es multi-threading (a menos que su objeto es verdaderamente inmutable). ¿Qué pasa si otro hilo cambió el estado del objeto para que el captador devuelva un valor diferente en la segunda llamada? No hay una manera fácil para que el compilador haga ninguna garantía, p. en el siguiente escenario:

class List 
{ 
    IList data; 

    // called several times on thread A 
    // property has no side-effects 
    public int Count { get data.Length; } 

    // called several times on thread B 
    public void Add(object o) 
    { 
     data.Add(o); 
    } 
} 
+0

DateTime.Now es una propiedad que no cambia el estado, pero cambia el valor de todos modos. Muchas otras propiedades reflejan el estado que se puede cambiar por otros medios además del setter. –

+0

@Albin Sunnanbo: 'DateTime.Now' no es un buen ejemplo aquí porque es estático y * devuelve * un nuevo tipo de valor. No hay estado ni valor cambiado. El hecho es que el OP quiere tener un mecanismo que garantice que las llamadas posteriores a la misma propiedad (al menos en un entorno de subproceso único) produzcan el mismo resultado. –

+0

+1, esto definitivamente recibe un voto, pero lo que realmente me pregunto es, si usted ha seguido las recomendaciones, ¿hay alguna manera de forzar al compilador a darse cuenta de que múltiples propiedades obtendrán el mismo valor, y por lo tanto compilarlos como si declarara una variable local primero si usa el mismo valor de propiedad varias veces en el mismo ámbito. –

2

supongo que estás buscando readonly, sin embargo no estoy seguro de cómo el rendimiento se compara con una variable local. Y solo es aplicable a los campos, no a las propiedades.

Además de readonly no implica determinismo.

private readonly List<string> fixedList = new List<string>(); 

solo significa que el objeto fixedList no puede ser reemplazado, pero el contenido puede ser cambiado.

Cuestiones relacionadas