Quando usar [Pure] em um construtor?


19

Estou aprendendo sobre contratos de código no .NET e tentando entender a idéia de construtores puros. o documentação dos contratos de código declara:

Todos os métodos chamados dentro de um contrato devem ser puros; isto é, eles não devem atualizar nenhum estado preexistente. Um método puro pode modificar objetos que foram criados após a entrada no método puro.

E a PureAttributedocumentação declara:

Indica que um tipo ou método é puro, ou seja, não faz nenhuma alteração visível no estado.

Eu entendo essas declarações quando se trata de métodos, mas e os construtores? Suponha que você tenha uma classe como esta:

public class Foo
{
    public int Value { get; set; }

    public Foo(int value) {
        this.Value = value;
    }
}

Esse construtor obviamente afeta o estado do novo Fooobjeto, mas não tem outros efeitos colaterais (por exemplo, ele não manipula nenhum dos parâmetros ou chama métodos não puros). Este candidato é [Pure]ou não? Qual é o significado de colocar um [Pure]atributo em um construtor e quando devo fazer isso no meu próprio código?

Respostas:


14

Você decora um método com [Pure]:

  • Se o método não tiver efeitos colaterais. Por exemplo, se o método acessa um banco de dados e o modifica ou seu resultado depende do banco de dados, não é puro.

  • E se você espera usá-lo em contratos de código. Por exemplo, se o método for puro , mas você não pretender usá-lo em contratos de código, a adição [Pure]não trará benefícios e não tornará seu código mais rápido.

No que diz respeito aos construtores, parece que eles são considerados puros no .NET e não precisam de um atributo explícito. Eu olhei para vários construtores na fonte do .NET Framework, como DateTime, e eles não têm [Pure]atributo.

Suponho que isso seja feito por vários motivos:

  • Pode ser muito impraticável ter que escrever um construtor sem parâmetros com [Pure]atributo apenas para poder usar a classe / estrutura em um contrato.

  • Alguns, como String, não possuem construtores explícitos.

  • Os construtores recebem tratamento especial mesmo fora dos contratos de código; por exemplo, você não deve lançar exceções dentro deles .

  • [Pure]é apenas uma convenção que está aqui para simplificar sua vida, mas não há verificação estática real para garantir que o método decorado com esse atributo seja puro. void DestroyDatabase()pode ser decorado como puro e os contratos de código não notarão nada de errado.

    Atualmente, não há nenhum componente de contratos de código que verifique se os métodos declarados puros são realmente puros. Portanto, se um programador decorou um método com [Pure], apenas acredita-se.

    Dos contratos de código # 5: Pureza do método

  • O próprio .NET Framework contém construtores que não são puros. Por exemplo, List<T>(IEnumerable<T> collection)é realmente impuro se o loop pela coleção tiver efeitos colaterais.

  • Os contratos gritam sejam simples. Posso facilmente imaginar um contrato como Contract.Requires(!string.IsNullOrEmpty(name)), por isso, existem boas razões para declarar a estática string.IsNullOrEmptypura.

    Por outro lado, se você precisar de um StringBuilderpara construir a cadeia de caracteres, verificará alguma coisa chamando um método de instância da sua classe de negócios, provavelmente está abusando dos contratos. É também por isso que StringBuilder.ToStringnão é marcado como puro, mesmo que seja (não é?)


Muitos contratos de código nos tipos de sistema são assumidos pelo verificador de contrato, incluindo " qualquer método cujo nome totalmente qualificado comece com" System.Diagnostics.Contracts.Contract "," System.String "," System.IO.Path "ou" System . Digite " ". Infelizmente, não tenho certeza se olhar para os tipos .NET é muito útil quando se trata de contratos de código.
Pwg

3
A pureza é uma daquelas coisas em que todo código chamado também precisa ser puro, ou o chamador não é "puro". Acho difícil acreditar que todos os construtores são considerados puros por padrão.
Frank Hileman

@FrankHileman: eu também. Eu não tenho um compilador C # agora, mas seria suficiente escrever uma classe com um construtor e nenhum [Pure]atributo e usá-la em outro lugar do contrato para obter uma resposta definitiva.
Arseni Mourzenko

1

O objeto não pode ser usado até que seja construído neste caso. Portanto, o construtor é puro. Se o construtor chamasse outro código ou invocasse um delegado, e o outro código modificasse a propriedade mutável, isso não seria puro. Para ser mais seguro, é melhor tornar a propriedade imutável.


Portanto, um construtor puro é um método puro que pode alterar o estado da classe atual, desde que satisfaça as outras condições de ser puro? BTW, a propriedade é mutável porque eu queria enfatizar que essa classe em si não é pura.
Pwg

@pswg: Você criou uma pergunta interessante que provavelmente deve ser respondida pela Microsoft. Suponha que o construtor chame um método que modifique a propriedade mutável; o construtor ainda seria puro? Eu acho que tecnicamente não seria, mesmo que a modificação seja "invisível" para os espectadores externos. Como não há outro código invocado no seu exemplo original, ele deve ser puro por qualquer definição que eu possa pensar.
Frank Hileman

@pswg: Exceto que o conjunto de propriedades também é uma chamada de método. Acho que você deveria perguntar nos fóruns do MSDN.
Frank Hileman

Acho que se a idéia central da pureza é se o método faz ou não alterações observáveis , nesse sentido, independentemente de chamar ou não métodos não puros, desde que as alterações não possam ser observadas por qualquer chamador, ainda seria um método puro.
Pwg

@pswg: Essa é a definição abstrata. Mas se eu estivesse escrevendo um analisador para essas coisas, provavelmente uma chamada de método não pura também seria considerada para tornar o chamador não puro. Apenas pela simplicidade da implementação. A questão é: é um construtor uma chamada de método normal ou qual a profundidade da análise.
Frank Hileman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.