Quand utiliser [Pure] sur un constructeur?

19

J'apprends les contrats de code dans .NET et j'essaie de comprendre l'idée de constructeurs purs. La documentation des contrats de code indique:

Toutes les méthodes appelées dans un contrat doivent être pures; c'est-à-dire qu'ils ne doivent mettre à jour aucun état préexistant. Une méthode pure est autorisée à modifier les objets qui ont été créés après l'entrée dans la méthode pure.

Et la PureAttributedocumentation indique:

Indique qu'un type ou une méthode est pur, c'est-à-dire qu'il n'apporte aucun changement d'état visible.

Je comprends ces affirmations en matière de méthodes, mais qu'en est-il des constructeurs? Supposons que vous ayez eu un cours comme celui-ci:

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

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

Ce constructeur affecte évidemment l'état du nouvel Fooobjet, mais il n'a pas d'autres effets secondaires (par exemple, il ne manipule aucun des paramètres et n'appelle aucune méthode non pure). Est-ce un candidat [Pure]ou non? Quelle est l'importance de placer un [Pure]attribut sur un constructeur, et quand dois-je le faire dans mon propre code?

pswg
la source

Réponses:

14

Vous décorez une méthode avec [Pure]:

  • Si la méthode n'a pas d'effets secondaires. Par exemple, si la méthode accède à une base de données et la modifie ou si son résultat dépend de la base de données, ce n'est pas pur.

  • Et si vous prévoyez de l'utiliser dans des contrats de code. Par exemple, si la méthode est pure , mais que vous n'avez pas l'intention de l'utiliser dans des contrats de code, l'ajout [Pure]n'aurait aucun avantage et ne rendra pas votre code plus rapide.

En ce qui concerne les constructeurs, il semble qu'ils soient supposés être purs en .NET et n'ont pas besoin d'un attribut explicite. J'ai regardé plusieurs constructeurs dans la source .NET Framework, tels que DateTime, et ils n'ont pas d' [Pure]attribut.

Je suppose que cela se fait pour plusieurs raisons:

  • Il peut être trop difficile d'avoir à écrire un constructeur sans paramètre avec [Pure]attribut juste pour pouvoir utiliser la classe / structure dans un contrat.

  • Certains, comme String, n'ont pas de constructeurs explicites.

  • Les constructeurs bénéficient d'un traitement spécial même en dehors des contrats de code; par exemple, vous n'êtes pas censé jeter des exceptions à l'intérieur .

  • [Pure]est juste une convention qui est là pour vous simplifier la vie, mais il n'y a pas de vérification statique réelle pour vous assurer que la méthode décorée avec cet attribut est pure. void DestroyDatabase()peut être décoré comme étant pur, et les contrats de code ne remarqueront rien de mal.

    Actuellement, aucun composant des contrats de code ne vérifie si les méthodes déclarées pures le sont vraiment. Ainsi, si un programmeur a décoré une méthode avec [Pure], c'est juste cru.

    Extrait des contrats de code n ° 5: pureté de la méthode

  • .NET Framework lui-même contient des constructeurs qui ne sont pas purs. Par exemple, List<T>(IEnumerable<T> collection)est en fait impur si le fait de parcourir la collection a des effets secondaires.

  • Les contrats doivent rester simples. Je peux facilement imaginer un contrat tel que Contract.Requires(!string.IsNullOrEmpty(name)), donc il y a de bonnes raisons de déclarer le statique string.IsNullOrEmptypur.

    D'un autre côté, si vous avez besoin d'un StringBuilderafin de construire la chaîne, vous vérifierez alors quelque chose en appelant une méthode d'instance de votre classe affaires, vous utilisez probablement mal les contrats. C'est aussi pourquoi StringBuilder.ToStringn'est pas marqué comme pur, même s'il pourrait l'être (n'est-ce pas?)

Arseni Mourzenko
la source
De nombreux contrats de code sur les types de système sont assumés par le vérificateur de contrat, y compris " toute méthode dont le nom complet commence par" System.Diagnostics.Contracts.Contract "," System.String "," System.IO.Path "ou" System .Tapez " ". Malheureusement, je ne sais pas si regarder les types .NET est trop utile en ce qui concerne les contrats de code.
pswg
3
La pureté est l'une de ces choses où tout le code appelé doit également être pur, ou l'appelant n'est pas "pur". J'ai du mal à croire que tous les constructeurs soient considérés comme purs par défaut.
Frank Hileman
@FrankHileman: moi aussi. Je n'ai pas de compilateur C # pour le moment, mais il suffirait d'écrire une classe avec un constructeur et aucun [Pure]attribut, et de l'utiliser ailleurs dans un contrat pour avoir une réponse définitive.
Arseni Mourzenko
1

L'objet ne peut pas être utilisé tant qu'il n'est pas construit dans ce cas. Le constructeur est donc pur. Si le constructeur appelait un autre code, ou invoquait un délégué, et que l'autre code modifiait la propriété mutable, ce ne serait pas pur. Pour être plus sûr, il vaut mieux rendre l'immeuble immuable.

Frank Hileman
la source
Donc, un constructeur pur est une méthode pure qui est autorisée à changer l'état de la classe actuelle, tant qu'elle satisfait aux autres conditions d'être pur? BTW, La propriété est modifiable car je voulais souligner que cette classe elle-même n'est pas pure.
pswg
@pswg: Vous avez créé une question intéressante à laquelle Microsoft doit probablement répondre. Supposons que le constructeur ait invoqué une méthode qui a modifié la propriété mutable; le constructeur serait-il encore pur? Je pense que techniquement, ce ne serait pas le cas, même si la modification est "invisible" pour les téléspectateurs externes. Puisqu'il n'y a pas d'autre code invoqué dans votre exemple d'origine, il doit être pur selon toute définition à laquelle je peux penser.
Frank Hileman
@pswg: Sauf que l'ensemble de propriétés est également un appel de méthode .. Je pense que vous devriez demander sur les forums MSDN.
Frank Hileman
Je suppose que si l'idée centrale de la pureté est de savoir si la méthode apporte ou non des changements observables , alors dans ce sens, qu'elle appelle ou non des méthodes non pures, tant que les changements ne peuvent être observés par aucun appelant, ce serait encore une méthode pure.
pswg
@pswg: C'est la définition abstraite. Mais si j'écrivais un analyseur pour ces choses, probablement un appel de méthode non pur serait également considéré pour rendre l'appelant non pur. Juste pour la simplicité de mise en œuvre. La question est alors de savoir si un constructeur est un appel de méthode normal ou quelle est la profondeur de l'analyse.
Frank Hileman