Sono zucchero sintattico per due cose diverse. Il primo inizializza un campo di supporto e lo imposta nell'espressione a destra del compito durante l'inizializzazione del campo. Quest'ultimo crea un get
che fa esattamente ciò che è nell'espressione.
public override bool CanRead { get; } = true;
è equivalente a
private readonly bool __backingFieldCanRead = true;
public override bool CanRead
{
get
{
return __backingFieldCanRead;
}
}
Questo
public override bool CanRead => true;
è equivalente a
public override bool CanRead
{
get
{
return true;
}
}
Si comportano in modo diverso. Il primo caso imposta il valore della proprietà quando viene creato l'oggetto e il campo viene inizializzato, l'altro caso valuta l'espressione ogni volta che viene richiamato il getter della proprietà. Nel caso semplice di un bool, il comportamento è lo stesso. Tuttavia se l'espressione causa effetti collaterali, le cose sono diverse. Considerare questo esempio:
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++;
}
Qui, "0, 1, 2, 3" vengono stampati. Il campo statico viene incrementato ogni volta che viene richiamato il getter della proprietà. Tuttavia, con un inizializzatore struttura:
public int Baz { get; } = counter++;
Poi "0, 0, 1, 1" viene stampato perché l'espressione viene valutata nel costruttore dell'oggetto.
Tecnicamente nel primo caso il campo di backing generato non è anche 'readonly'? – Kyle
Il campo di supporto viene assegnato come se fosse assegnato nell'inizializzatore del campo, non nel corpo del costruttore. È possibile osservare questa differenza se la classe base chiama un metodo virtuale, che si verifica prima dell'esecuzione del corpo del costruttore. È una sottile differenza, ammettiamolo :) –
@JonSkeet Oh, hai ragione, il campo è "initonly". – vcsjones