Question

Ayons un objet créé dans un getter comme ceci:

public class Class1
{
       public string Id { get; set; }
       public string Oz { get; set; }
       public string Poznamka { get; set; }

       public Object object
       {
             get
             {
                  // maybe some more code
                  return new Object { Id = Id, poznamla = Poznamka, Oz = OZ };
             }
        }
 }

Ou devrais-je créer plutôt une méthode qui permettra de créer et de renvoyer l'objet?

Était-ce utile?

La solution

Propriétés ressemblent à des champs, mais ce sont des méthodes. Cela a été connu pour provoquer une quantité phénoménale de confusion. Quand un programmeur voit code qui semble accéder à un champ, il y a beaucoup d'hypothèses que le programmeur fait cela ne peut pas être vrai pour un property.So il y a quelques propriétés communes des lignes directrices de conception.

  1. renoncions différentes valeurs du getter de la propriété. Si elle est appelée plusieurs fois dans une rangée, une méthode de propriété peut renvoyer une valeur différente à chaque fois; un champ renvoie la même valeur à chaque fois.

  2. Une méthode de propriété peut nécessiter de la mémoire supplémentaire ou renvoyer une référence à quelque chose qui est ne fait pas partie de l'état de l'objet, afin de modifier l'objet retourné n'a aucun effet sur l'objet original; interrogeant un champ renvoie toujours une référence à un objet qui est garanti pour faire partie de l'état de l'objet original. Travailler avec une propriété qui retourne une copie peut être très déroutant pour les développeurs, et cette caractéristique est souvent pas documentée.

  3. Considérons qu'une propriété ne peut pas être passé comme un paramètre out ou ref un procédé; un champ peut.

  4. Évitez apporteurs de propriété de longue course. Une méthode de propriété peut prendre beaucoup de temps pour exécuter; l'accès sur le terrain se termine toujours immédiatement.

  5. éviter de jeter des exceptions à getters.

  6. Faites préserver les valeurs précédentes si un setter de propriété renvoie une exception

  7. Évitez les effets secondaires observables.

  8. Permettre aux propriétés à fixer dans l'ordre même si cela aboutit à un état non valide temporaire d'objets.

Sources

" CLR via C # ", Jeffrey Richter. Chapitre 9. Définition des propriétés Intelligemment

"" 2e édition, Brad Abrams, Krzysztof Cwalina , chapitre 5.2 design propriété

Autres conseils

Oui, il est une mauvaise pratique.

Idéalement, un getter ne doit pas être en train de changer quoi que ce soit ou de créer (en dehors de chargement paresseux, et même alors je pense qu'il conduit à moins de code clair ...). De cette façon, vous réduisez le risque d'effets secondaires non intentionnels.

Si vous voulez que votre getter pour créer un nouvel objet à chaque fois qu'il est accessible, c'est la façon de le faire. Ce modèle est normalement refered comme un Méthode Factory.

Cependant, ce n'est pas normalement nécessaire sur les propriétés (ie. Accesseurs), et en tant que telle est considérée comme une mauvaise pratique.

oui, il est ... de l'extérieur, il doit être transparent, si vous accédez à une propriété ou un champ ...

lors de la lecture deux fois du champ, ou une propriété, vous vous attendez deux choses:

  • il n'y a pas d'impact sur le comportement de l'objet (externe)
  • vous obtenez des résultats identiques

Je n'ai pas connaissance réelle de C #, mais je l'espère, ce qui suit fait mon point clair. Commençons comme ceci:

Object o1 = myInst.object;
Object o2 = myInst.object;
o1.poznamka = "some note";

dans le cas d'un champ, des conditions telles que seront vraies:

o1 == o2;
o2.poznamka == "some note";

si vous utilisez une propriété avec un getter, qui retourne un nouvel objet à chaque fois appelé, les deux conditions seront fausses ...

votre getter semble être destiné à produire un instantané temporaire de votre exemple ... si c'est ce que vous voulez faire, que faire une méthode simple ... il évite toute ambiguïté ...

Une propriété devrait, à toutes fins utiles, agir comme un champ. Cela signifie aucune exception ne devrait être jeté, et aucun nouvel objet doit être créé (vous ne créent pas beaucoup d'objets unneccessary si la propriété est utilisée dans une boucle)

Utilisez une classe wrapper ou similaire à la place.

Selon moi, si quelque chose est « propriété » getter devrait vous renvoyer une propriété (essentiellement une donnée qui est déjà existant) correspondant à l'objet.

Dans votre cas, vous retournez quelque chose qui est pas une propriété de cet objet à ce moment-là. Vous n'êtes pas retournerez une propriété de votre objet, mais un produit d'une action.

Je voudrais aller avec une méthode quelque chose comme GetMyObject () au lieu. Surtout s'il y a une « action » aura lieu, je pense qu'il est la plupart du temps préférable d'avoir une méthode qu'une propriété nom .

Et essayez d'imaginer ce que seraient les autres développeurs qui ne connaissent pas votre code attendre après avoir vu votre propriété.

Une propriété est juste un moyen pratique d'exprimer un champ calculé.

Il devrait représenter encore quelque chose à propos un objet, quelle que soit la façon dont la valeur elle-même est arrivé à. Par exemple, si l'objet en question est une facture, vous devrez peut-être ajouter le coût de chaque élément de la ligne, et le retour du total.

Qu'est-ce qui est écrit dans la question casse cette règle, car en retournant une copie de l'objet n'est pas quelque chose qui décrit l'objet. Si la valeur de retour des changements entre les appels à la propriété sans changement explicite d'état de l'objet , le modèle d'objet est cassé.

Pour parler en termes généraux, le retour d'un nouvel objet comme celui-ci va à peu près toujours briser la règle (je ne peux pas penser à un contre-exemple en ce moment), je dirais que c'est une mauvaise pratique.

Il y a aussi la chasse aux sorcières des propriétés où vous pouvez facilement et innocemment appeler sur une propriété plusieurs fois et finir par exécuter le même code (qui ne tarde pas à nous l'espérons!).

Pour l'écriture de code qui est facilement testé, vous devez maintenir la séparation de l'initialisation de l'objet.

i.e. alors que dans les cas de test que vous ne disposez pas d'attente sur le test des éléments spécifiques.

comme dans l'objet Maison vous ne voulez tester quoi que ce soit lié à l'objet de la cuisine. et vous wana seul test le jardin. Ainsi, alors que vous lancez une classe maison et initiez objet dans certains constructeurs ou getters vous ne serez pas bon de codage qui soutiendra le test.

En aparté aux commentaires déjà fait, vous pouvez rencontrer quelques maux de tête de débogage réels lorsque les champs de chargement paresseux via une propriété.

J'avais une classe avec

private Collection<int> moo;

public Collection<int> Moo
{
  get 
  {
    if (this.moo == null) this.moo = new Collection<int>();
    return this.moo;
  }
}

Alors quelque part ailleurs dans la classe il y avait une méthode publique qui fait référence

this.moo.Add(baa);

sans le vérifier est instancié.

Il a jeté une exception de référence null, comme prévu. Mais l'exception est sur un thread d'interface utilisateur afin de ne pas immédiatement évident où il venait. J'ai commencé à tracer à travers, et chaque fois que je traçais à travers, l'erreur dissapeared.

Pendant un certain temps, je dois admettre que je pensais que je devenais fou. Debugger - aucune erreur. Erreur d'exécution. Une grande partie de la tête éraflure plus tard, je repéré l'erreur, et se rendit compte que le débogueur Visual Studio a été instancié avec la collection qu'il affiche les propriétés publiques de la classe.

Il est peut-être au plus acceptable pour structs. Pour les types de référence, je voudrais créer seulement un nouvel objet dans un getter quand il est fait seulement une fois en utilisant un certain modèle de charge paresseux.

Cela dépend de l'utilisation du getter. Il est un excellent endroit pour inclure ce genre de code pour le chargement paresseux.

Il est une mauvaise pratique. Dans votre exemple, vous devriez être en mesure d'attendre le même Object chaque fois que vous accédez à la propriété object.

Comme vous l'avez, il est mauvais mais pas dis similaire à une pratique acceptable appelé le chargement paresseux qui peut être lu ici.

http: // www .aspcode.net / Lazy-chargement-de-structures-en-C-howto-partie-8.aspx

Il est une mauvaise pratique. Mais si vous pensez des objets comme un tas de getters et setters vous devriez vérifier les discussions classiques sur le sujet.

Comme mentionné certaines personnes, le chargement paresseux pourrait être une raison de le faire. Cela dépend de la logique métier réelle que vous modélisez ici. Vous devez créer une méthode distincte si elle est mieux à des fins de lisibilité, mais si le code pour créer l'objet est simple, vous pouvez éviter le indirection.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top