C#: comment implémenter et utiliser un attribut NotNull et CanBeNull

je veux laisser les programmeurs et moi-même savons qu'une méthode ne veux pas null et si vous envoyez null de toute façon, le résultat ne sera pas assez.

il y a un NotNullAttribute et CanBeNullAttributeBibliothèques Partagées De Lokad, dans le Lokad.Quality espace de noms.

Mais comment cela fonctionne? J'ai regardé le code source de ces deux attributs, et il ressemble à ceci:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter |
                AttributeTargets.Property | AttributeTargets.Delegate |
                AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
[NoCodeCoverage]
public sealed class NotNullAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter |
                AttributeTargets.Property | AttributeTargets.Delegate |
                AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
[NoCodeCoverage]
public sealed class CanBeNullAttribute : Attribute
{
}

deux classes vides héritant de Attribute. Comment sont-ils utilisés? Faire vous devez chercher de la documentation xml et savoir qu'elle existe? Parce que j'ai essayé à la fois de faire ma propre copie de l'attribut et d'utiliser la version Lokad, mais quand j'ai essayé d'envoyer un null directement, je n'ai reçu aucun message. Ni de ReSharper ni de VS. Ce à quoi je m'attendais en fait. Mais comment sont-ils utilisés? Est-ce que je peux d'une façon ou d'une autre créer des avertissements pour moi si J'essaie d'envoyer quelque chose qui est nul là-dedans? Ou est-il utilisé dans une sorte de cadre de test? Ou?

39
demandé sur Dan Neely 2009-04-27 11:35:59

4 réponses

à mi-parcours ,Les "contrats codes" (en 4.0) seront une meilleure réponse à cette question. Ils sont maintenant disponibles (avec scolaire ou commercial licences), mais sera plus intégré dans VS2010. Ceci peut fournir à la fois une analyse statique et un support d'exécution.

(edit) exemple:

Contract.RequiresAlways( x != null );

Simple que cela... le moteur de contrats de code fonctionne au niveau IL, de sorte qu'il peut analyser cela et jeter des avertissements/erreurs d'appel de code pendant la construction, ou à Runtime. Pour la compatibilité ascendante, si vous avez le code de validation existant, vous pouvez simplement lui dire où se termine la vérification de bon sens, et il fera le reste:

if ( x == null ) throw new ArgumentNullException("x");
Contract.EndContractBlock();
46
répondu Marc Gravell 2009-04-27 08:00:33

ceci peut être fait avec AOP, où un Conseil vérifie à l'exécution si un paramètre de méthode est nul et si nulls est autorisé. Voir PostSharpSpring.NET for AOP.

en ce qui concerne ReSharper, voir Cadre Annoté:

nous avons analysé une grande partie de la bibliothèque .net Framework Class, ainsi que NUnit Framework, et nous l'avons annotée à l'aide de fichiers XML externes, en utilisant un ensemble de les attributs de la JetBrains.Les Annotations de l'espace de noms, en particulier:

  • StringFormatMethodAttribute (pour les méthodes qui prennent des chaînes de format comme paramètres)
  • InvokerParameterNameAttribute (pour les méthodes avec littéral de chaîne d'arguments qui devraient correspondre à l'un des paramètres de l'appelant)
  • AssertionMethodAttribute (pour les méthodes d'assertion)
  • AssertionConditionAttribute (pour les paramètres de méthodes d'assertion)
  • TerminatesProgramAttribute (pour les méthodes qui résilier le contrôle de flux)
  • CanBeNullAttribute (pour les valeurs qui peuvent être nulles)
  • NotNullAttribute (pour les valeurs qui ne peuvent pas être null)
19
répondu Anton Gogolev 2009-04-27 07:43:18

ces annotations sont pour ReSharper, et sont copiées des JetBrains.Les Annotations de l'espace de noms. Un framework peut les mettre dans leur propre espace de noms, cependant, ReSharper ne récupérera pas ces annotations automatiquement - vous devez dire à ReSharper d'utiliser l'espace de noms personnalisé dans la boîte de dialogue options. Une fois que vous avez sélectionné le nouvel espace de noms, L'analyse de ReSharper prendra les attributs et vous donnera des highlights et des avertissements.

6
répondu citizenmatt 2013-10-31 14:28:21

Comme indiqué par Anton Gogolev, les attributs peuvent être créés en utilisant PostSharp.(notez que CodeContract utilise des appels de méthode statiques à l'intérieur du corps de la méthode)

mise à jour février 2013: la nouvelle version 3.0 de PostSharp (actuellement en Beta) sera prise en charge validation des paramètres, des champs et des propriétés

1) Article valider-paramètres-aide-attributs a la mise en oeuvre de

public class NotEmpty : ParameterAttribute

public class NotNull: ParameterAttribute

[AttributeUsage (AttributeTargets.Paramètre)]

public abstract class ParameterAttribute: attribut

{

public abstract void CheckParameter(ParameterInfo parameter, object value); 

}

il fallait aussi un attribut de méthode avec un aspect de limite de méthode pour traiter les attributs de paramètre.

2) dans le commentaire à l'article il y a des liens vers très de mise en œuvre similaire for NonNull/non empty

[retour: non] public SomeObject SomeMethod ([Non] AnotherObject param1)      

le code source est situé dans Google Code Torch / DesignByContract

3) un autre exemple plus compliqué est décrit dans http://badecho.com/2011/11/validating-method-parameters-with-postsharp/

3
répondu Michael Freidgeim 2017-05-23 10:31:09