¿Cuál es la diferencia entre las propiedades auto solo de getter y las propiedades del cuerpo de expresión?


En C# 6, puede simplificar la implementación de una propiedad mediante el uso de una propiedad automática de solo getter. Por ejemplo, si estuviera implementando la clase abstract Stream:

public override bool CanRead { get; } = true;

Sin embargo, también puedo escribirlo con un cuerpo de expresión, también nuevo en C # 6:

public override bool CanRead => true;

¿Cuál es la diferencia entre los dos, y cuándo debo usar uno u otro?

 49
Author: vcsjones, 2015-01-13

2 answers

Son azúcar sintáctica para dos cosas diferentes. El primero inicializa un campo de respaldo y lo establece en la expresión del lado derecho de la asignación durante la inicialización del campo. Este último crea un get que hace exactamente lo que está en la expresión.

public override bool CanRead { get; } = true;

Es equivalente a

private readonly bool __backingFieldCanRead = true;

public override bool CanRead
{
    get
    {
        return __backingFieldCanRead;
    }
}

Esto

public override bool CanRead => true;

Es equivalente a

public override bool CanRead
{
    get
    {
        return true;
    }
}

Se comportan de manera diferente. El primer caso establece el valor de la propiedad cuando se crea el objeto y el campo son inicializado, el otro caso evalúa la expresión cada vez que se invoca el getter de la propiedad. En el caso simple de un bool, el comportamiento es el mismo. Sin embargo, si la expresión causa efectos secundarios, las cosas son diferentes. Considere este ejemplo:

class Program
{
    static void Main(string[] args)
    {
        var fooBar1 = new FooBar();
        Console.WriteLine(fooBar1.Baz);
        Console.WriteLine(fooBar1.Baz);
        var fooBar2 = new FooBar();
        Console.WriteLine(fooBar2.Baz);
        Console.WriteLine(fooBar2.Baz);
    }
}

public class FooBar
{
    private static int counter;
    public int Baz => counter++;
}

Aquí, "0, 1, 2, 3" están impresos. El campo estático counter se incrementa cada vez que se invoca el getter de la propiedad. Sin embargo, con un inicializador de propiedades:

public int Baz { get; } = counter++;

Entonces se imprime" 0, 0, 1, 1 " porque la expresión es evaluado en el constructor del objeto.

 55
Author: vcsjones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-12 21:54:04

En el caso que describes en nuestro ejemplo, solía preferir:

public override bool CanRead { get; } = true;

Pero hoy he notificado que esta implementación causa una asignación de memoria para el campo de respaldo. Y así, esta implementación: bool CanRead => true; puede guardar 4 bytes.

 2
Author: Orace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-10 16:22:11