48 votes

Comment éviter la récursivité de la propriété

Ça m'a frappé récemment sur un projet sur lequel je travaillais. La plupart des gens sont familiers avec la propriété de la récursivité:

public int Test 
{
   get { return this.test; }
   set { this.Test = value; }
}
private int test;

Vous avez accidentellement mis une majuscule T dans ce setter, et que vous avez ouvert vous-même jusqu'à un StackoverflowException. Pire encore, si vous n'avez pas défini, souvent, visual studio va s'auto-corriger le boîtier pour vous à l'état non valide.

J'ai fait quelque chose de similaire, mais, dans un constructeur récemment:

public TestClass(int test)
{
    this.Test = Test;
}

Malheureusement, ici vous n'obtenez pas une StackOverflowException, maintenant vous avez une erreur de programmation. Dans mon cas, cette valeur a été passé à un WebService qui a plutôt utilisé une valeur par défaut (ce qui n'est pas 0), ce qui m'a fait passer à côté du fait que j'avais mal attribué. Les tests d'intégration sont tous passés, parce que le service n'a pas dit

"Hey, vous avez oublié ce vraiment important champ!"

Que puis-je faire pour éviter ce genre de comportement? J'ai toujours conseillé à l'encontre de la définition des variables comme le suivant, et je n'aime pas personnellement, mais je ne peux pas penser à d'autres options:

private int _test;
private int mTest;

MODIFIER

Raisons que le trait de soulignement ou m préfixe sont indésirables normalement que je peux penser sont:

  • La lisibilité
  • Un peu plus difficile à faire défiler les membres si vous êtes héritant de la 3e partie des classes que vous obtenez un mélange de styles.

62voto

Sriram Sakthivel Points 33463

Le meilleur moyen est d'utiliser "Propriétés implémentées automatiquement" ici.

 public int Test { get; set; }
 

S'il n'est pas possible d'utiliser les "propriétés implémentées automatiquement" pour une raison quelconque, utilisez le préfixe _ (je ne préfère pas cependant)

Ou obtenez un Resharper, il signalera immédiatement votre erreur stupide.

33voto

David Points 65209

Les tests d'intégration sont tous passés

Alors qu'ils n'étaient pas assez exhaustifs tests. Si il y a une erreur qui n'a pas été découvert par les tests, alors vous avez un autre test à écrire.

C'est vraiment la seule solution automatisée ici. Le compilateur ne va pas se plaindre, parce que le code est structurellement et syntaxiquement correct. C'est juste pas logique au moment de l'exécution.

Vous pouvez définir des normes de nommage, voire d'utiliser des outils comme StyleCop pour tenter de faire appliquer ces normes. Ce serait sans doute de vous permettre de vous couvrir beaucoup de choses, mais ce n'est pas une solution à toute épreuve et des erreurs peuvent encore passer. Personnellement, je suis d'accord avec vous que la décoration de noms de variable est inesthétique dans le code. Peut-être, dans certains cas, il est valide d'un compromis?

En fin de compte, les tests automatisés sont votre défense contre ces types d'erreurs. Pour faire simple, si une erreur se fait grâce à vos tests et dans la production, alors la réponse doit être:

  1. Écrire un test pour reproduire l'erreur.
  2. Correction de l'erreur.
  3. Utiliser le test pour valider la correction.

Accordées, qui ne couvre qu' un seul cas, pas à chaque définition de propriété dans votre code. Mais si cela se passe beaucoup de choses , alors vous pourriez avoir un problème personnel et non pas d'un problème technique. Quelqu'un de l'équipe est, bien, bâclée. La solution à ce problème ne peut pas être une technique.

6voto

Slavo Points 5585

L'utilisation des extraits de code.

Pour chaque propriété, soutenu par un champ privé, utiliser un extrait de code que vous avez créé, au lieu d'écrire à partir de zéro ou de laisser IntelliSense de faire le travail (mal).

Après tout, ce problème est sur les conventions et de la discipline, plutôt que de la langue de conception. Le cas de la nature sensible de C# et de la subperfect de complétion de code dans Visual Studio sont la raison pour laquelle nous faisons de ces erreurs, pas notre manque de connaissance et de conception.

Vous meilleur pari ici est d'éliminer les risques d'accidents et d'avoir un prédéfini pour l'écriture de ces répétitif choses correctement, c'est la meilleure façon d'aller. Il est également beaucoup plus automatisé, comparativement à se souvenir de conventions et de les appliquer à la main.

Il y a par défaut un extrait de code dans Visual Studio pour cette. Type propfull et de cliquer sur l'Onglet, puis spécifiez la variable d'instance nom et le nom de la propriété et vous êtes bon pour aller.

3voto

Robert Points 230

Dans certains cas, vous ne pouvez pas contourner les setters et les getters. Mais peut-être que vous n'avez pas besoin des setters et des getters si vous suivez le principe du Tell, Don't Ask? En gros, il est préférable de préférer que l'objet contenant les données effectue le travail et non un autre objet qui interroge beaucoup l'objet de données, prenne des décisions, puis réécrit les données dans l'objet de données. Voir http://martinfowler.com/bliki/TellDontAsk.html

2voto

Phil Cooper Points 605

Ne pourriez-vous pas simplement écrire un test pour couvrir cela?

 int constructorValue = 4;
TestClass test = new TestClass(constructorValue);
Assert.Equals(test.Test, constructorValue);
 

Vous ne voudrez peut-être pas écrire immédiatement des tests pour vous protéger des oscillations futures, mais vous avez trouvé un bogue, pourquoi ne pas vous en protéger à nouveau?

Pour mémoire, si j’ai besoin d’un champ privé pour stocker la valeur d’un getter / setter pulic, je le souligne toujours. Il y a juste quelque chose d'un soulignement qui crie l'intimité!

 public string Test
{
    get { return _test; }
    set { _test = value; }
}

private string _test;
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X