Diferença em C # entre diferentes estilos de getter

154

Às vezes, vejo abreviações nas propriedades do getter. Por exemplo, esses dois tipos:

public int Number { get; } = 0

public int Number => 0;

Alguém pode me dizer se existem diferenças entre os dois. Como eles se comportam? Os dois são somente leitura?

WoIIe
fonte

Respostas:

266

Sim, os dois são somente leitura, mas há uma diferença. No primeiro, há um campo de apoio que é inicializado como 0 antes que o construtor seja executado. Você pode alterar o valor apenas no construtor , assim como um campo somente leitura regular. O getter em si apenas retorna o valor do campo.

No segundo, o getter retorna 0 sempre, sem campo envolvido.

Portanto, para evitar o uso de propriedades implementadas automaticamente ou de membros com expressão, temos:

Primeira versão

private readonly int _number = 0;
public int Number { get { return _number; } }

Segunda versão

public int Number { get { return 0; } }

Um exemplo mais claro da diferença pode ser visto assim:

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

Se você criar um único objeto, sua CreationTimepropriedade sempre fornecerá o mesmo resultado - porque é armazenada em um campo somente leitura, inicializado na construção do objeto. No entanto, toda vez que você acessar a CurrentTimepropriedade, isso fará com DateTime.UtcNowque seja avaliado, para que você obtenha um resultado potencialmente diferente.

Jon Skeet
fonte
23
Observe que a segunda versão nem sempre retorna o mesmo valor. Um bom exemplo é se você retornar random.NextInt(). A primeira versão avaliará isso uma vez e sempre terá o mesmo valor. O segundo retornará um novo valor a cada vez.
248

Uma diferença é quando isso 0é avaliado: na criação do objeto ou quando a propriedade é usada.

Você pode ver isso melhor com as propriedades DateTime:

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

A Startpropriedade continua retornando no mesmo horário (de quando a instância foi criada), enquanto Nowmuda para refletir o horário atual.

Explicação :

A primeira versão ("Iniciar") fornece um valor inicial que pode até ser substituído pelo construtor. Portanto, isso é avaliado apenas uma vez.
A segunda versão ("Now") fornece a expressão que será o "getter" dessa propriedade. Portanto, isso é avaliado toda vez que a propriedade é lida. Não existe nem um campo de apoio que o construtor possa sobrescrever.

Hans Keing
fonte
26
Essa é a distinção mais importante que eu acho.
Mateus
14
A resposta aceita define com mais precisão a diferença no código de exemplo, mas isso explica uma diferença mais útil nas duas estruturas.
Kamil Drakari
3
Uau, você recebeu mais votos do que o famoso Jon Skeet.
machine_1
21

Esses são os recursos de linguagem C # 6.

Primeiro exemplo

public int Number { get; } = 0

O primeiro exemplo é uma propriedade automática somente getter . O campo de apoio de uma propriedade automática somente para getter é declarado implicitamente como somente leitura.

Segundo exemplo

public int Number => 0;

E o segundo exemplo são corpos de expressão em membros de funções semelhantes a propriedades . Observe que não há nenhuma getpalavra-chave: está implícita no uso da sintaxe do corpo da expressão.

Ambos são somente leitura.

Jehof
fonte
5
... mas, como Jon Skeet explica, você pode alterar o valor que o primeiro retorna.
Martin Bonner apoia Monica
2
@MartinBonner ... mas apenas no construtor.
Dennis Kuypers
5
ou, como sempre, por meio de reflexão (minúcias menor)
Marco Pf