сравнение экземпляров атрибута
Теперь, когда вы умеете находить экземпляры атрибутов в коде, имеет смысл рас-
смотреть процедуру проверки значений, хранящихся в их полях. Можно, к примеру,
написать код, явным образом проверяющий значение каждого поля класса атрибута.
Однако класс
System.Attribute
переопределяет метод
Equals
класса
Object
, за-
ставляя его сравнивать типы объектов. Если они не совпадают, метод возвращает
значение
false
. В случае же совпадения метод
Equals
использует отражения для
сравнения полей двух атрибутов (вызывая метод
Equals
для каждого поля). Если
478
Глава.18 .Настраиваемые.атрибуты
все поля совпадают, возвращается значение
true
. Можно переопределить метод
Equals
в вашем собственном классе атрибутов, убрав из него отражения и повысив
тем самым производительность.
Класс
System.Attribute
содержит также виртуальный метод
Match
, который
вы можете переопределить для получения более богатой семантики. По умолчанию
данный метод просто вызывает метод
Equals
и возвращает полученный результат.
Следующий код демонстрирует переопределение методов
Equals
и
Match
(значение
true
возвращается, если один атрибут представляет собой подмножество другого)
и применение второго из них:
using System;
[Flags]
internal enum Accounts {
Savings = 0x0001,
Checking = 0x0002,
Brokerage = 0x0004
}
[AttributeUsage(AttributeTargets.Class)]
internal sealed class AccountsAttribute : Attribute {
private Accounts m_accounts;
public AccountsAttribute(Accounts accounts) {
m_accounts = accounts;
}
public override Boolean Match(Object obj) {
// Если в базовом классе реализован метод Match и это не
// класс Attribute, раскомментируйте следующую строку
// if (!base.Match(obj)) return false;
// Так как 'this' не равен null, если obj равен null,
// объекты не совпадают
// ПРИМЕЧАНИЕ. Эту строку можно удалить, если вы считаете,
// что базовый тип корректно реализует метод Match
if (obj == null) return false;
// Объекты разных типов не могут быть равны
// ПРИМЕЧАНИЕ. Эту строку можно удалить, если вы считаете,
// что базовый тип корректно реализует метод Match
if (this.GetType() != obj.GetType()) return false;
// Приведение obj к нашему типу для доступа к полям
// ПРИМЕЧАНИЕ. Это приведение всегда работает,
// так как объекты принадлежат к одному типу
AccountsAttribute other = (AccountsAttribute) obj;
// Сравнение полей
// Проверка, является ли accounts 'this' подмножеством
// accounts объекта others
if ((other.m_accounts & m_accounts) != m_accounts)
479
Сравнение.экземпляров.атрибута
return false;
return true; // Объекты совпадают
}
public override Boolean Equals(Object obj) {
// Если в базовом классе реализован метод Equals и это
// не класс Object, раскомментируйте следующую строку
// if (!base.Equals(obj)) return false;
// Так как 'this' не равен null, при obj равном null
// объекты не совпадают
// ПРИМЕЧАНИЕ. Эту строку можно удалить, если вы считаете,
// что базовый тип корректно реализует метод Equals
if (obj == null) return false;
// Объекты разных типов не могут совпасть
// ПРИМЕЧАНИЕ. Эту строку можно удалить, если вы считаете,
// что базовый тип корректно реализует метод Equals
if (this.GetType() != obj.GetType()) return false;
// Приведение obj к нашему типу для получения доступа к полям
// ПРИМЕЧАНИЕ. Это приведение работает всегда,
// так как объекты принадлежат к одному типу
AccountsAttribute other = (AccountsAttribute) obj;
// Сравнение значений полей 'this' и other
if (other.m_accounts != m_accounts)
return false;
return true; // Объекты совпадают
}
// Переопределяем GetHashCode, так как Equals уже переопределен
public override Int32 GetHashCode() {
return (Int32) m_accounts;
}
}
[Accounts(Accounts.Savings)]
internal sealed class ChildAccount { }
[Accounts(Accounts.Savings | Accounts.Checking | Accounts.Brokerage)]
internal sealed class AdultAccount { }
public sealed class Program {
public static void Main() {
CanWriteCheck(new ChildAccount());
CanWriteCheck(new AdultAccount());
// Просто для демонстрации корректности работы метода для
// типа, к которому не был применен атрибут AccountsAttribute
продолжение
480
Do'stlaringiz bilan baham: |