Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

17.4.1Атрибут AttributeUsage

Атрибут AttributeUsage используется для описания способа использования класса атрибута.

Класс, к которому добавлен атрибут AttributeUsage, должен быть производным от System.Attribute, прямо или косвенно. В противном случае произойдет ошибка времени компиляции.

namespace System { [AttributeUsage(AttributeTargets.Class)] public class AttributeUsageAttribute: Attribute { public AttributeUsageAttribute(AttributeTargets validOn) {...}

public virtual bool AllowMultiple { get {...} set {...} }

public virtual bool Inherited { get {...} set {...} }

public virtual AttributeTargets ValidOn { get {...} } }

public enum AttributeTargets { Assembly = 0x0001, Module = 0x0002, Class = 0x0004, Struct = 0x0008, Enum = 0x0010, Constructor = 0x0020, Method = 0x0040, Property = 0x0080, Field = 0x0100, Event = 0x0200, Interface = 0x0400, Parameter = 0x0800, Delegate = 0x1000, ReturnValue = 0x2000,

All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate | ReturnValue } }

17.4.2Атрибут Conditional

Атрибут Conditional дает возможность вводить определение условных методов и классов условных атрибутов.

namespace System.Diagnostics { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)] public class ConditionalAttribute: Attribute { public ConditionalAttribute(string conditionString) {...}

public string ConditionString { get {...} } } }

17.4.2.1Условные методы

Метод, к которому добавлен атрибут Conditional, является условным методом. Атрибут Conditional указывает условие путем проверки символа условной компиляции. Вызовы условного метода или включаются, или опускаются, в зависимости от того, определен ли этот символ в точке вызова. Если символ определен, вызов включается; иначе вызов (включая оценку выражения-получателя и параметров вызова) опускается.

Для условного метода имеются следующие ограничения:

  • условный метод должен быть методом в объявлении_класса или объявлении_структуры. Если атрибут Conditional указан для метода в объявлении интерфейса, возникает ошибка времени компиляции;

  • условный метод должен иметь тип возвращаемого значения void;

  • условный метод не должен быть помечен модификатором override. Однако условный метод может быть помечен модификатором virtual. Переопределения такого метода являются неявно условными и они не должны явно помечаться атрибутом Conditional;

  • условный метод не должен быть реализацией метода интерфейса. Иначе возникает ошибка времени компиляции.

Кроме того, ошибка времени компиляции возникает, если условный метод используется в выражении_создания_делегата. Например:

#define DEBUG

using System; using System.Diagnostics;

class Class1 { [Conditional("DEBUG")] public static void M() { Console.WriteLine("Executed Class1.M"); } }

class Class2 { public static void Test() { Class1.M(); } }

Здесь Class1.M объявлен как условный метод. Метод Test класса Class2 вызывает этот метод. Так как символ условной компиляции DEBUG определен, если вызывается метод Class2.Test, то он вызовет M. Если бы символ DEBUG не был определен, то метод Class2.Test не вызвал бы Class1.M.

Обратите внимание, что включение или исключение вызова условного метода управляется символами условной компиляции в точке вызова. В этом примере

Файл class1.cs:

using System.Diagnostics;

class Class1 { [Conditional("DEBUG")] public static void F() { Console.WriteLine("Executed Class1.F"); } }

Файл class2.cs:

#define DEBUG

class Class2 { public static void G() { Class1.F(); // F is called } }

Файл class3.cs:

#undef DEBUG

class Class3 { public static void H() { Class1.F(); // F is not called } }

Здесь каждый из классов Class2 и Class3 содержит вызовы условного метода Class1.F, обусловленного тем, определен или нет символ DEBUG. Так как этот символ определен в контексте Class2, но не в Class3, вызов F в Class2 включен, тогда как вызов F в Class3 опущен.

Использование условных методов в цепочке наследования может привести к путанице. Вызовы условного метода посредством base в виде base.M подчиняются обычным правилам вызова условного метода. В этом примере

Файл class1.cs:

using System; using System.Diagnostics;

class Class1 { [Conditional("DEBUG")] public virtual void M() { Console.WriteLine("Class1.M executed"); } }

Файл class2.cs:

using System;

class Class2: Class1 { public override void M() { Console.WriteLine("Class2.M executed"); base.M(); // base.M is not called! } }

Файл class3.cs:

#define DEBUG

using System;

class Class3 { public static void Test() { Class2 c = new Class2(); c.M(); // M is called } }

Здесь Class2 включает вызов метода M, определенного в его базовом классе. Этот вызов опускается, так как базовый метод является условным, базированным на наличии символа DEBUG, который здесь не определен. Таким образом, метод записывает на консоль только сообщение «Class2.M выполнен». Разумное использование ПРО_описаний может устранить такие проблемы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]