it-swarm-fr.com

Lance une exception d'une forme de propriété?

J'ai toujours été de la mentalité que les propriétés (c.-à-d. Leurs opérations de jeu/get) doivent être rapides/immédiates et sans échec. Vous ne devriez jamais avoir à essayer/attraper une propriété.

Mais je cherche certains moyens d'appliquer la sécurité basée sur un rôle sur les propriétés de certains objets. Par exemple un employé.Salaire. Certaines des solutions que j'ai rencontrées dans lesquelles d'autres ont essayé (l'une en particulier est l'exemple de AOP ici ) implique de jeter une exception si l'accesseur n'a pas les bonnes autorisations - mais cela va à l'encontre d'une règle personnelle que j'ai eu depuis longtemps maintenant.

Alors je demande: je me trompe? Avoir changé les choses? A-t-il été accepté que les propriétés devraient être en mesure de lancer des exceptions?

16
Steven Evers

lorsque vous définissez la valeur d'une propriété, lancez une exception sur une valeur non valide.

obtenir la valeur d'une propriété devrait (presque) ne jamais jeter une exception

pour l'accès basé sur le rôle, utilisez des interfaces ou des façades différentes/dumber; Ne laissez pas les gens voir des choses qu'ils ne peuvent pas avoir!

15
Steven A. Lowe

Je dirais certainement qu'il y a une faille dans la conception si vous ressentez la nécessité de lancer des exceptions à partir d'un constructeur de propriétés ou de getter.

Une propriété est une abstraction qui représente quelque chose qui est juste une valeur . Et vous devriez être capable de définir une valeur sans craindre que cela puisse faire une exception. *

Si la définition de la propriété entraîne un effet secondaire, cela devrait vraiment être mis en œuvre comme une méthode. Et s'il ne produit aucun effet secondaire, aucune exception ne devrait être lancée.

Un exemple déjà mentionné dans une réponse différente est le Stream.Position propriété. Cela produit des effets secondaires et peut lancer des exceptions. Mais ce constructeur de propriétés est essentiellement juste un wrapper autour Stream.Seek que vous pouviez appeler à la place.

Personnellement, je pense que la position n'aurait pas dû être une propriété écrite.

Un autre exemple où vous pourriez être tenté de lancer une exception à partir d'un constructeur de propriétés est dans la validation des données:

public class User {
    public string Email {
        get { return _email; }
        set { 
            if (!IsValidEmail(value)) throw InvalidEmailException(value);
            _email = value;
        }
    }

Mais il y a une meilleure solution à ce problème. Introduisez un type représentant une adresse électronique valide:

public class Email {
    public Email(string value) {
        if (!IsValidEmail(value)) throw new InvalidEmailException(value);
        ...
    }
    ...
}

public class User {
    public Email Email { get; set; }
}

La classe Email garantit qu'il ne peut pas contenir une valeur qui n'est pas une adresse électronique valide et des classes qui doivent stocker des courriels sont relevés du devoir de les valider.

Cela conduit également à une cohésion plus élevée (un indicateur de bonne conception logicielle) - les connaissances sur ce qu'est une adresse électronique et la manière dont elle est validée n'existe que dans la classe Email, qui n'a que cette préoccupation.

* ObjectDisposedException est la seule exception valide (aucun jeu de mots destiné à) que je puisse penser pour le moment.

4
Pete

Le point d'une propriété est le principe d'accès uniforme , c'est-à-dire que une valeur doit être accessible via la même interface que la même interface soit mise en œuvre par stockage ou calcul. Si votre propriété lance une exception qui représente une condition d'erreur au-delà du contrôle du programmeur, le type censé être attrapé et géré, vous forcez votre client à savoir que la valeur est obtenue via un calcul.

D'autre part, je ne vois aucun problème à utiliser des affirmations ou des exceptions telles que des exceptions visant à signaler une utilisation incorrecte de l'API au programmeur plutôt que d'être pris et manipulée. Dans ces cas, la réponse correcte du point de vue de l'utilisateur de l'API n'est pas de gérer l'exception (prenant ainsi implicitement de savoir si la valeur est obtenue via un calcul ou un stockage). C'est pour corriger son code afin que l'objet ne se retrouve pas dans un état non valide ou vous permet de réparer votre code afin que l'affirmation ne s'agisse pas.

2
dsimcha

Je sais que votre question est spécifique à .NET , mais depuis C # partage une histoire avec Java, je pensais que vous pourriez être intéressé. Je suis non en quelque sorte impliquant que, parce que quelque chose se fait en Java, cela devrait être fait en C #. Je sais que les deux sont très différents, surtout dans la manière dont C # a une prise en charge de la langue beaucoup améliorée aux propriétés. Je donne juste un certain contexte et une perspective.

Du Spécification JavaBeans :

Propriétés contraintes Parfois, lorsqu'un changement de propriété survient, un autre haricot peut souhaiter valider le changement et le rejeter s'il est inapproprié. Nous nous référons à des propriétés qui subissent ce type de vérification comme des propriétés contraignantes. In Java Beans, des méthodes de constructeur de biens contraintes sont nécessaires pour prendre en charge la propriétéVetoException. Ces documents aux utilisateurs de la propriété contrainte qui tente des mises à jour peuvent être veto. Donc, une simple propriété contrainte pourrait ressembler à:

PropertyType getFoo();
void setFoo(PropertyType value) throws PropertyVetoException;

Prenez tout cela avec un grain de sel, s'il vous plaît. La spécification Javabeans est ancienne et les propriétés C # sont (OMI) une amélioration énorme sur les propriétés basées sur la "convention de dénomination" qui Java a. Je tente juste de donner un peu de contexte, est tout !

2
Mike Clark

AFAIK, cette directive provient principalement du processus de pensée que les propriétés peuvent être utilisées à -conception fois. (E.g. La propriété de texte sur une zone de texte) Si la propriété jette une exception lorsqu'un designer tente d'y accéder, VS ne va pas passer une bonne journée. Vous obtiendrez un tas d'erreurs essayant d'utiliser le designer et pour les concepteurs d'interface utilisateur, ils ne vont pas rendant. Cela s'applique également au temps de débogage également, bien que vous verrez dans un scénario d'exception, ce n'est que "Exception XXX" et il ne figure pas de CLOBBER VS IIRC.

Pour les Pocos, cela ne fera aucun mal, mais je tire toujours de le faire moi-même. Je pense que les gens voudront accéder aux propriétés plus fréquemment, afin qu'ils soient normalement peu coûteux. Les propriétés ne doivent pas faire le travail des méthodes, ils devraient simplement obtenir/définir certaines informations et être effectués en règle générale.

1
MIA