Почему .Net лучше всего проектировать пользовательские атрибуты как закрытые? - PullRequest
30 голосов
/ 23 октября 2011

Я читаю Pro C # 2010 и платформу .Net 4 Эндрю Троелсена.

В главе 15 об атрибутах есть примечание:

Примечание: В целях безопасности считается наилучшей практикой .Net для разработки всех пользовательских атрибутов как запечатанных.

Автор не объясняет почему, кто-то может объяснить почему?

Ответы [ 3 ]

32 голосов
/ 23 октября 2011

CA1813: избегайте незапечатанных атрибутов: Библиотека классов .NET Framework предоставляет методы для извлечения пользовательские атрибуты. По умолчанию эти методы ищут атрибут иерархия наследования; например Attribute.GetCustomAttribute ищет указанный тип атрибута или любой тип атрибута, который расширяет указанный тип атрибута. Запечатывание атрибута устраняет поиск по иерархии наследования, и может улучшить производительность.

Ссылка: https://docs.microsoft.com/visualstudio/code-quality/ca1813-avoid-unsealed-attributes

Атрибуты - это просто метаданные, обнаруженные во время выполнения. Как указывается, если кто-то еще наследует ваш пользовательский класс атрибутов, по умолчанию .NET также найдет их, что может означать угрозу безопасности, если производный класс атрибутов изменяет поведение вашего исходного атрибута так, как вы никогда не предполагали к.

Несмотря на то, что производительность является основной причиной запечатывания классов атрибутов, здесь есть грозная статья, касающаяся ее безопасности .

4 голосов
/ 15 мая 2014

Есть еще одна причина запечатать атрибуты.

Рассмотрим следующий атрибут:

[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false)]
public class Attr1 : Attribute
{
}

Здесь вы разрешаете только оформление одного атрибута: AllowMultiple = false

Компилятор не разрешит это:

[Attr1]
[Attr1]
public class Foo
{
}

Позже в вашем коде вы можете безопасно вызывать memberInfo.GetCustomAttribute(), который выдаст AmbiguousMatchException, если будет найдено более одного атрибута данного типа.

Давайте теперь унаследуем:

public class Attr2 : Attr1
{
}

Теперь компилятор молчит.

[Attr1]
[Attr2]
public class Foo
{
}

Так что если позже кто-то унаследует ваш атрибут и вернет его в ваш код, то будет сгенерирована сущность, отмеченная обоими атрибутами.Полный пример:

class Program
{
    static void Main(params string[] args)
    {
        typeof(Foo).GetCustomAttribute<Attr1>();
    }

    [AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class Attr1 : Attribute
    {
    }

    public class Attr2 : Attr1
    {
    }

    [Attr1]
    [Attr2]
    public class Foo
    {
    }

    [Attr1]
    public class Bar : Foo
    {
    }
}
1 голос
/ 23 октября 2011

Руководство по разработке структуры: соглашения, идиомы и шаблоны для многократно используемых библиотек .NET просто говорит:

DO печать пользовательских классов атрибутов, если это возможно. Это ускоряет поиск атрибута.

Я не видел ничего о безопасности в этом разделе, но @Teoman Soygul делает хорошую мысль. Так что я бы согласился с мистером Троелсеном.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...