2010-11-05 5 views
18

Est-il possible d'utiliser l'attribut Obsolète uniquement sur un accesseur ou un accesseur de propriété?Est-il possible d'utiliser l'attribut Obsolète uniquement sur un accesseur ou un accesseur de propriété

Je voudrais pouvoir faire quelque chose comme ceci:

public int Id { 
    get { return _id;} 
    [Obsolete("Going forward, this property is readonly",true)] 
    set { _id = value;} 
} 

mais il est évident que ne construirai pas. Y a-t-il un travail qui me permet d'appliquer cet attribut uniquement au setter?

+1

Puisque vous l'avez mis à soulever des erreurs, pourquoi ne pas supprimer tout simplement le poseur, ils vont être informé qu'il est en lecture seule. – Doggett

+1

Vous pouvez toujours désactiver l'erreur en utilisant la directive '#pragma warning', même s'il ne s'agit pas seulement d'un avertissement. De cette façon, le code existant sera toujours construit, tandis que le code futur ne le sera pas. –

Répondre

9

Je pense que cela ne peut pas être fait parce que, pour une raison quelconque, il a été spécifiquement interdit pour l'attribut Obsolète. Selon les règles définies autour des cibles d'attribut, il ne semble pas y avoir de raison pour que l'attribut Obsolète ne soit pas valide sur une propriété get ou set accessor. Pour appliquer un attribut à un accesseur de jeu de propriétés, that attribute must be applicable to either a method, parameter, or return value target. Si vous regardez the Obsolete attribute, vous pouvez voir que "méthode" est l'une des cibles valides pour cet attribut. En fait, vous pouvez définir votre propre attribut avec les mêmes cibles valides que l'attribut Obsolète with the AttributeUsage attribute, et vous constaterez que vous pouvez l'appliquer à une propriété get ou set accessor alors que vous ne pouvez pas appliquer l'attribut Obsolete.

[AttributeUsage(AttributeTargets.Method)] 
class MyMethodAttribute : Attribute { } 

class MyClass 
{ 
    private int _Id; 

    public int Id 
    { 
     get { return _Id; } 

     [MyMethodAttribute] // this works because "Method" is a valid target for this attribute 
     [Obsolete] // this does not work, even though "Method" is a valid target for the Obsolete attribute 
     set { _Id = value; } 
    } 
} 

Si vous essayez de créer votre propre attribut non valide sur un accesseur ensemble de la propriété et que vous appliquez là, vous remarquerez peut-être le message d'erreur est légèrement différente. Le message d'erreur de votre attribut personnalisé sera "Attribute 'YourCustomAttribute' n'est pas valide pour ce type de déclaration.", Alors que le message d'erreur "Obsolete 'n'est pas valide sur les accesseurs de propriété ou d'événement." Le fait que le message d'erreur soit différent me fait croire qu'il s'agit d'une règle explicitement intégrée dans le compilateur de l'attribut Obsolète, plutôt que de s'appuyer sur l'attribut AttributeUsage qui est soi-disant appliqué à l'attribut Obsolète. .

+0

Le 'ObsoletteAttribute' est' sealed' ... – Shimmy

+1

@Shimmy Je ne suggérais pas de dériver une classe de 'ObsoleteAttribute', mais expliquais simplement les observations qui m'ont amené à croire que cette restriction sur l'utilisation de l'attribut Obsolète est déterminé par l'implémentation du compilateur, pas par les règles d'utilisation de l'attribut .NET. Je ne sais pas pourquoi le fait que la classe soit scellée compte. –

+0

@ Dr.Willy, je l'ai manqué désolé ... J'ai une propriété dont j'ai besoin pour être en lecture-écriture, mais je ne veux pas que l'écriture soit utilisée, je dois seulement remplir une exigence de contrat, le 'ObsoleteAttribute' pourrait être utile ici. – Shimmy

0

J'avais le même problème aujourd'hui et j'avais une solution qui fonctionnait pour des objets de données simples qui n'ont pas de logique propre. Au lieu de rendre le setter obsolète (ce qui ne fonctionne pas pour les raisons mentionnées dans les autres réponses), j'ai rendu obsolète le constructeur lui-même et en ai introduit un nouveau où je fournis la valeur initiale. Cela suppose que le constructeur par défaut a été exécuté pour créer l'instance de la classe. Peut-être que tu devrais en marquer un autre.

Cependant, nous ne pouvez pas utiliser les propriétés implémentées automatiquement dans ce cas, afin de pouvoir définir la valeur initiale dans le constructeur:

class MyClass 
{ 
    [Obsolete("Use the constructor with param myProperty instead")] MyClass() { } 
    MyClass(MyProperty m) { this.m_MyProperty = m; } 

    public MyType MyProperty 
    { 
     get { return this.m_MyProperty; } 
     set { this.m_MyProperty = value; } 
    } 
} 

Donc, en fait, je créé une readonly-propriété dont la valeur peut seulement être fixé par le constructeur. Toute attemp créer une instance par son défaut constructeur et de définir sa propriété ne produira pas le compilateur d'avertissement pour le poseur mais pour l'instanciation - ce qui est correct dans mon cas:

var m = new MyClass(); // here we get warning/error now 
m.MyProperty = 

Soyez conscient que ce doesn Ne travaillez pas si votre propriété ne doit pas être réglée à partir du en dehors de. Ceci est lorsque sa valeur est calculée dans votre nouveau code:

MyProperty { get { return /* some computation */ } } 
Questions connexes