Propriedade automatizada apenas com getter, pode ser definida, por quê?

96

Criei uma propriedade automatizada:

public int Foo { get; } 

Isso é apenas getter. Mas quando eu construo um construtor, posso mudar o valor:

public MyClass(string name)
{
    Foo = 5;
}

Por que isso é possível, embora seja apenas para obter?

Noam B.
fonte
Na verdade, ele não usa um setter (porque não tem um). Ele define diretamente o campo subjacente (que está oculto para nós, por isso você precisa usar o nome da propriedade)
Dennis_E
14
Para que serve uma propriedade, se ela nunca pode ser inicializada / definida? Yacoub Massad respondeu perfeitamente
Vikhram

Respostas:

123

Este é um novo recurso do C # 6, "propriedades automáticas somente de obtenção", também conhecido como "Inicializadores de propriedade automática para propriedades somente leitura", conforme discutido neste artigo da revista MSDN 'C #: The New and Improved C # 6.0' por Mark Michaelis e na especificação da linguagem de rascunho do C # 6.0 .

O setter do campo somente leitura é acessível apenas no construtor; em todos os outros cenários, o campo ainda é somente leitura e se comporta como antes.

Esta é uma sintaxe de conveniência para reduzir a quantidade de código que você precisa digitar e para remover a necessidade de declarar explicitamente uma variável de nível de módulo privado para conter o valor.

Esse recurso foi visto como importante porque, desde a introdução das propriedades implementadas automaticamente no C # 3, as propriedades mutáveis ​​(aquelas com um getter e setter) tornaram-se mais rápidas de escrever do que as imutáveis ​​(aquelas com apenas um getter), o que significa que as pessoas eram ser tentado a usar propriedades mutáveis ​​para evitar ter que digitar o código para um campo de apoio geralmente necessário para propriedades somente leitura. Há mais discussão sobre as propriedades implementadas automaticamente na seção relevante do Guia de programação do Microsoft C # .

Esta postagem do blog, '# 1.207 - C # 6.0 - Inicializadores de propriedade automática para propriedades somente leitura', de Sean Sexton, tem uma boa explicação e um exemplo como segue:

Antes do C # 6.0, se você quisesse uma propriedade somente leitura (imutável), normalmente usaria um campo de apoio somente leitura que é inicializado no construtor, conforme mostrado abaixo.

public class Dog 
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    private readonly DateTime creTime;
    public DateTime DogCreationTime 
    {
        get { return creTime; }
    }

    public Dog(string name)
    {
        Name = name;
        creTime = DateTime.Now;
    }
}

No C # 6.0, você pode usar propriedades implementadas automaticamente para implementar uma propriedade somente leitura. Você faz isso usando um inicializador de propriedade automática. O resultado é muito mais limpo do que o exemplo acima, onde tivemos que declarar explicitamente um campo de apoio.

public class Dog
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    public DateTime DogCreationTime { get; } = DateTime.Now;

    public Dog(string name)
    {
        Name = name;
    }
}

Mais detalhes também podem ser encontrados no repositório dotnet Roslyn no GitHub :

As propriedades automáticas agora podem ser declaradas sem um setter.

O campo de apoio de uma propriedade automática somente getter é declarado implicitamente como somente leitura (embora isso importe apenas para fins de reflexão). Ele pode ser inicializado por meio de um inicializador na propriedade como no exemplo acima. Além disso, uma propriedade somente getter pode ser atribuída no corpo do construtor do tipo declarante, o que faz com que o valor seja atribuído diretamente ao campo subjacente:

Trata-se de expressar tipos de forma mais concisa, mas observe que também remove uma diferença importante na linguagem entre tipos mutáveis ​​e imutáveis: as auto-propriedades eram uma forma abreviada disponível apenas se você estivesse disposto a tornar sua classe mutável e, portanto, a tentação de usar o padrão para isso foi ótimo. Agora, com as propriedades automáticas somente getter, o campo de jogo foi nivelado entre mutável e imutável.

e na especificação de linguagem de rascunho C # 6.0 (NB: A especificação de linguagem é final no que diz respeito à Microsoft, mas ainda não foi aprovada como um padrão EMCA / ISO , daí o 'rascunho'):

Propriedades implementadas automaticamente

Uma propriedade implementada automaticamente (ou propriedade automática para abreviar) é uma propriedade não abstrata e não externa com corpos de acessador apenas de ponto-e-vírgula. As propriedades automáticas devem ter um acessador get e, opcionalmente, um acessador set.

Quando uma propriedade é especificada como uma propriedade implementada automaticamente, um campo de suporte oculto fica automaticamente disponível para a propriedade e os acessadores são implementados para ler e gravar nesse campo de suporte. Se a propriedade automática não tiver nenhum acessador definido, o campo de apoio será considerado somente leitura (campos somente leitura). Assim como um campo somente leitura, uma propriedade automática somente getter também pode ser atribuída no corpo de um construtor da classe envolvente. Essa atribuição é atribuída diretamente ao campo de apoio somente leitura da propriedade.

Uma propriedade automática pode opcionalmente ter um property_initializer, que é aplicado diretamente ao campo de apoio como um variable_initializer (inicializadores de variável).

tomRedox
fonte
1
Este é um design estúpido. Isso deve ser um erro de tempo de compilação se definido em um local onde a propriedade é considerada somente leitura.
Shiv
A esquisitice para mim é que ainda há um erro do compilador que diz CS0200 C# Property or indexer cannot be assigned to -- it is read onlyao usar uma propriedade regular. As "propriedades automáticas somente getter" são consideradas somente leitura ou não?
Kyle Delaney
24

Este é um novo recurso no C # 6 que permite criar propriedades somente leitura e inicializar seus valores a partir do construtor (ou embutido quando você os declara).

Se você tentar alterar o valor desta propriedade fora do construtor, ocorrerá um erro de compilação.

É somente leitura no sentido de que, depois de inicializar seu valor (embutido ou dentro do construtor), você não pode alterar seu valor.

Yacoub Massad
fonte
Então, qual é a explicação? Qual é a definição de getter?
Noam B.
16

Se não fosse possível inicializar a propriedade somente leitura do construtor (ou um inicializador de propriedade automática), seria inútil, pois sempre retornaria o valor padrão para seu tipo (0 para números, nulo para tipos de referência ) A mesma semântica aplicada a campos somente leitura em todas as versões C #.

Para definir uma propriedade somente getter verdadeira (que não pode ser inicializada a partir do construtor), você precisa especificar o que ela retorna como parte da definição:

public int Foo { get { return 5; } }

Ou, de forma mais concisa em C # 6:

public int Foo => 5;
Douglas
fonte
Não é totalmente verdade, as propriedades somente leitura são muito úteis para encapsular alguma condição em seu código. Você pode escrever uma instrução if e quase qualquer código para avaliar outras propriedades ou condições e retornar um valor apropriado sempre que ler a propriedade
sebagomez
3
@sebagomez: Não tenho certeza se estou entendendo - não foi isso que demonstrei no meu exemplo?
Douglas
5

“Propriedades implementadas automaticamente somente leitura”

Em primeiro lugar, quero esclarecer que a propriedade como

public string FirstName { get; }

É conhecido como “propriedades implementadas automaticamente somente leitura”

Para verificar isso, você pode executar e verificar o código acima com o Visual Studio. Se você alterar a versão do idioma de C # 6.0 para C # 5.0, o compilador lançará a seguinte exceção recurso 'propriedades implementadas automaticamente somente leitura' não está disponível em C # 5. Use a versão de idioma 6 ou superior.

para alterar a versão do idioma C # visite aqui

Agora estou indo para sua segunda pergunta

“Este é apenas getter. Mas quando eu construo um construtor, posso mudar o valor ”

A Microsoft apresenta as “propriedades implementadas automaticamente somente leitura” na lógica de somente leitura. Como sabemos, a palavra-chave “somente leitura” está disponível em C # 1.0. usamos a palavra-chave "somente leitura" como modificador em um campo e esse campo pode ser atribuído de 2 maneiras , no momento da declaração ou em um construtor na mesma classe.

Da mesma forma, o valor de "propriedades implementadas automaticamente somente leitura" pode ser atribuído de 2 maneiras

Way1 (no momento da declaração):

public string FirstName { get; } = "Banketeshvar";

Way2 (em um construtor da mesma classe)

Person()
{
 FirstName  = "Banketeshvar";
}

Propriedade puramente somente leitura

Se você está procurando uma propriedade somente leitura, vá para esta

public string FullName => "Manish Sharma";

agora você não pode atribuir o valor da propriedade “FullName” do construtor. Se você tentar fazer isso, as seguintes exceções serão lançadas

“Propriedade ou indexador 'Person.FullName' não pode ser atribuído - é somente leitura”

Banketeshvar Narayan
fonte
2
note que FullName => "foo bar" será avaliado CADA VEZ.
1919
4

O recurso de propriedade automática foi adicionado à linguagem durante o lançamento do C # 3.0. Ele permite que você defina uma propriedade sem nenhum campo de apoio, no entanto, você ainda precisa usar o construtor para inicializar essas propriedades automáticas com o valor não padrão. C # 6.0 introduz um novo recurso chamado inicializador de propriedade automático, que permite inicializar essas propriedades sem um construtor como a seguir:

Anteriormente, um construtor é necessário se você deseja criar objetos usando uma propriedade automática e inicializar uma propriedade automática com um valor não padrão como abaixo:

public class MyClass
{
    public int Foo { get; }

    public Foo(int foo)
    {
        Foo = foo;
    }
}

Agora, no C # 6.0, a capacidade de usar um inicializador com a propriedade auto significa que nenhum código de construtor explícito é necessário.

public string Foo { get; } = "SomeString";

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };

Você pode encontrar mais informações sobre isso aqui

Rahul Nikate
fonte
1

Uma variável declarada readonlypode ser escrita dentro de um construtor, mas em linguagens que respeitam o atributo, não pode ser modificada após o retorno do construtor. Esse qualificador foi fornecido como um recurso de linguagem porque muitas vezes é necessário para campos cujos valores variam com base nos parâmetros do construtor (o que significa que eles não podem ser inicializados antes do início do construtor), mas não terão que mudar após o retorno dos construtores, mas foi utilizável apenas para variáveis ​​expostas como campos. A semântica dereadonly campos -qualified seria, em muitos casos, perfeita para membros públicos, exceto que geralmente é melhor para as classes expor os membros - mesmo os imutáveis ​​- como propriedades em vez de campos.

Assim como as propriedades automáticas de leitura e gravação existem para permitir que as classes exponham propriedades mutáveis ​​tão facilmente quanto os campos comuns, as propriedades automáticas somente leitura existem para permitir que as classes exponham propriedades imutáveis ​​tão facilmente quanto os readonlycampos qualificados. Assim como os readonlycampos -qualified podem ser escritos em um construtor, o mesmo ocorre com as propriedades get-only.

supergato
fonte