Самые полезные атрибуты

Я знаю, что атрибуты очень полезны. Есть несколько предопределенных, таких как [Browsable(false)], который позволяет скрывать свойства на вкладке свойств. Вот хороший вопрос, объясняющий атрибуты: Что такое атрибуты в .NET?

Какие предопределенные атрибуты (и их пространство имен) вы фактически используете в своих проектах?

Что за вопрос? , вся страница переполнена красивыми ответами с замечательными объяснениями. Пока я читал это, я получил опыт, например, опросил многих экспертов по поводу их взглядов. +100 за вопрос.

Muthu Ganapathy Nathan 07.05.2013 15:34

Я согласен, подобные вопросы - одни из самых ценных - они делают SO менее полезным, что закрываются.

David Thielen 19.04.2020 01:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
786
2
164 397
32

Ответы 32

[Serializable] постоянно используется для сериализации и десериализации объектов во внешние источники данных, такие как xml или с удаленного сервера, и из них. Подробнее об этом здесь.

Фактически это называется псевдоатрибутом, поскольку C# выдает флаг метаданных для [Serializable], а не экземпляр настраиваемого атрибута;)

TraumaPony 28.09.2008 04:50

Хотя [Serializable] очень полезен, он далек от совершенства. Чтобы получить желаемый результат, требуется слишком много усилий, проб и ошибок.

shoosh 04.01.2009 22:55

Я поддержу это!

John Bubriski 15.04.2009 04:17

System.NonSerializedAttribute полезен, если вам нужен больший контроль над автоматической сериализацией.

CSharper 29.04.2009 12:51

В качестве примечания я бы добавил, что производительность встроенной сериализации .Net довольно низкая, примерно на 2 или 3 порядка медленнее, чем код, созданный вручную.

redcalx 13.01.2010 14:52

[Flags] довольно удобен. Синтаксический сахар, конечно, но все же довольно приятный.

[Flags] 
enum SandwichStuff
{
   Cheese = 1,
   Pickles = 2,
   Chips = 4,
   Ham = 8,
   Eggs = 16,
   PeanutButter = 32,
   Jam = 64
};

public Sandwich MakeSandwich(SandwichStuff stuff)
{
   Console.WriteLine(stuff.ToString());
   // ...
}

// ...

MakeSandwich(SandwichStuff.Cheese 
   | SandwichStuff.Ham 
   | SandwichStuff.PeanutButter);
// produces console output: "Cheese, Ham, PeanutButter"

Леппи указывает на то, чего я не осознавал, и что скорее ослабляет мой энтузиазм по поводу этого атрибута: он дает команду нет компилятору разрешить битовые комбинации в качестве допустимых значений для переменных перечисления, компилятор позволяет это для перечислений независимо. Мой фон C++ просматривается через ... вздох

Итак, что именно делает атрибут Flags?

Andrei Rînea 28.09.2008 15:20

Я думаю, что перечисление должно наследовать от int, не так ли?

Martin Clarke 28.09.2008 21:43

@Andrei: превращает тип перечисления в тип битового поля с поддерживающими метаданными.

Shog9 28.09.2008 22:22

@Martin: int - это тип по умолчанию; если вам нужно что-то еще, вы должны это указать.

Shog9 28.09.2008 22:24

Я надеюсь, вы, ребята, понимаете, что атрибут Flags делает все возможное. Он вообще не нужен / не используется, кроме TypeConverter.

leppie 13.10.2008 13:27

@leppie: ToString () тоже. Но ... вау. По какой-то причине я ожидал, что поведение перечислений без атрибута будет таким же, как в C++: значения or'd производят целое число (не могут быть переданы как есть методу, ожидающему параметра enum). Теперь я понимаю, что это не так. Слабый ... хорошо, перечисления .NET - отстой.

Shog9 13.10.2008 21:46

[Flags] действительно только помогает отладчику и функциям .ToString () знать, что значение потенциально является комбинацией нескольких объявлений в перечислении. Я не уверен, может ли Intellisense помочь вам более эффективно использовать перечисление.

Kenzi 18.02.2012 20:19

[Flags] имеет большее применение, чем просто синтаксический сахар. При использовании веб-сервисов сериализация / десериализация не будет работать, если будет передано значение вроде SandwichStuff.Cheese | SandwichStuff.Ham | SandwichStuff.Jam. Без атрибута [Flags] десериализатор не узнает, что значение может быть комбинацией флагов. Я усвоил это на собственном горьком опыте, потратив около двух дней на размышления, почему мой WCF не работает.

Anchit 20.07.2012 11:33

@leppie следует использовать атрибут flags, чтобы указать, что вы можете использовать побитовое ИЛИ. Использование его в перечислениях, которые не отмечены им, вероятно, не будет иметь степени 2, что приведет к беспорядку.

Alexander 02.05.2019 17:42

Если бы я провел сканирование покрытия кода, я думаю, что эти два были бы лучшими:

 [Serializable]
 [WebMethod]

[WebMethod] используется для украшения метода, который предоставляется в веб-службе. [Serializable] помечает ваши объекты так, чтобы их можно было сериализовать для таких целей, как передача их между доменами приложений.

Kev 28.09.2008 05:28

В духе Хофштадта атрибут [Attribute] очень полезен, поскольку с его помощью вы создаете свои собственные атрибуты. Я использовал атрибуты вместо интерфейсов для реализации систем плагинов, добавления описаний в Enums, имитации множественной диспетчеризации и других трюков.

Звучит круто! Не могли бы вы показать несколько примеров системы плагинов и описаний перечислений? Я заинтересован в том, чтобы реализовать обе эти вещи!

John Bubriski 15.04.2009 04:17

На мой взгляд, System.Obsolete - один из самых полезных атрибутов в фреймворке. Возможность выдавать предупреждение о коде, который больше не следует использовать, очень полезна. Мне нравится иметь способ сказать разработчикам, что что-то больше не следует использовать, а также иметь способ объяснить, почему и указать на лучший / новый способ что-то делать.

Conditional attribute также очень удобен для отладки. Он позволяет добавлять в код методы для отладки, которые не будут компилироваться при сборке решения для выпуска.

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

Мне нравится флаг устаревшего, но он просто вызывает предупреждение. Большинство людей, с которыми я столкнулся, игнорируют предупреждения в VS

wusher 02.10.2008 21:49

Да, я тоже это заметил. Я работал над приложениями, где есть сотни предупреждений. Большинство из них нужно было исправить, но не по какой-то причине. Я никогда этого не понимал ...

Dan Herbert 04.10.2008 01:35

Вы можете передать «true» в качестве одного из параметров System.Obsolete, что приведет к тому, что предупреждение станет ошибкой, что приведет к нарушению сборки. Очевидно, это следует сделать после того, как вы удалите все предупреждения. :)

Adrian Clark 01.12.2008 05:36

После того, как вы очистите все предупреждения, не лучше ли просто удалить метод?

Pedro 16.01.2009 02:00

@Pedro: Иногда это невозможно по причинам обратной совместимости. Если он частный и неиспользуемый, да, удалите его.

Fantius 02.06.2009 20:55

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

plinth 16.09.2009 17:26

@plinth Создание исключения было бы плохой идеей по многим причинам. №1 заключается в том, что основная причина использования Obsolete () заключается в том, чтобы вы могли продолжать работу скомпилированного кода во время переходной фазы. Если вы не разрешаете никому вызывать метод, почему бы просто не удалить его?

Dan Herbert 16.09.2009 17:34

@Dan - если вы отметите Obsolete с ошибкой с ошибкой при компиляции, то он не должен вызываться Когда-либо. Если он вызывается во время выполнения, значит кто-то нарушил Устаревший ...

plinth 16.09.2009 17:57

@plinth Это предотвращает использование метода кодом новый. Старый код останется двоично-совместимым, если метод помечен как устаревший, но он перестанет работать, если вы создадите исключение. Если кто-то использует отражение, чтобы обойти флаг "Obsolte", то у вас проблемы похуже ...

Dan Herbert 16.09.2009 18:27

Недавно я написал статью об использовании условных атрибутов для отладки. На самом деле мне нравится использовать их больше, чем точки останова в определенных случаях. Вот несколько примеров ... codefromjames.com/wordpress/?p=131

jocull 23.08.2012 05:51

Если вы выпускаете свои библиотеки DLL как API с поддержкой версий, вы можете сохранить метод устаревших ошибок, чтобы люди могли получить информацию о том, почему он больше не работает, а не о том, что метод просто не существует. [Obsolete( "Use X instead", true )] указывает причину, по которой код не компилируется, и предлагает альтернативу.

Tarka 22.06.2017 19:15

Как бы то ни было, вот список всех атрибутов .NET. Их несколько сотен.

Я не знаю ни о ком другом, но мне нужно серьезно заняться RTFM!

опубликованный список для .net 1.1 вот список для 3.5 msdn.microsoft.com/en-us/library/system.attribute.aspx (вам нужно немного прокрутить вниз)

kay.one 30.06.2009 10:56

Обновил ссылку в вопросе. Теперь это полный список для 3.5

R. Martinho Fernandes 08.11.2009 16:17

Собственно то ссылки на последнюю, а не на 3.5 конкретно.

Brian Ortiz 27.06.2010 21:29

Вот если бы список был не просто списком ссылок, а именем и описанием. Ну что ж. @BrianOrtiz прав. Список находится в версии 4.5.

Luminous 10.09.2014 16:49

Вы просто меняете целевую платформу вверху, где написано «Другие версии».

Novaterata 06.02.2015 22:01
msdn.microsoft.com/en-us/library/… for a much larger and more recent list.
MathuSum Mut 19.02.2017 17:05

Я нашел [DefaultValue] весьма полезным.

[DebuggerDisplay] может быть действительно полезен для быстрого просмотра настроенного вывода типа при наведении указателя мыши на экземпляр типа во время отладки. пример:

[DebuggerDisplay("FirstName = {FirstName}, LastName = {LastName}")]
class Customer
{
    public string FirstName;
    public string LastName;
}

Вот так это должно выглядеть в отладчике:

alt text

Также стоит упомянуть, что атрибут [WebMethod] с набором свойств CacheDuration позволяет избежать ненужного выполнения метода веб-службы.

Вау, это действительно хорошо знать. Обычно я делал то же самое, переопределяя ToString, но это лучше.

Brian 16.09.2009 17:24

Будьте осторожны, он откусывает гораздо больший кусок вашего процессора, чем ToString.

Nikola Radosavljević 22.11.2011 04:42

Вы также можете использовать это для отображения результатов методов. Это может вызвать затруднения при отладке, если метод (или свойство get) имеет побочные эффекты.

Øyvind Skaar 25.10.2012 14:56

@ NikolaRadosavljević будет ли он потреблять мощность процессора только во время отладки

Nickolay Kondratyev 17.02.2013 10:19

@Nickolay Kondratyev: Я не знаю всех тонкостей, но вы можете взглянуть на следующие передовые практики веб-сервисов, которые помогут вам сделать некоторые выводы: blogs.msdn.com/b/jaredpar/archive/2011/03/18/…

Nikola Radosavljević 18.02.2013 14:33

@Nikola: там говорится только о производительности отладки.

Per Lundberg 07.10.2013 09:11

@Brian Почему так лучше, могу я спросить? Он достигает только одной цели, в то время как ToString достигает обеих. Я не уверен, что понимаю назначение этого атрибута.

MasterMastic 21.01.2014 23:59

@Ken: см. Зачем переопределять ToString ()?

Brian 22.01.2014 01:06

Каждый раз, когда у вас есть curly, оценивается внутренняя часть, на что тратится центральный процессор, 2x curly равняется 2x вызовам eval, поэтому чрезмерное количество вызовов может стоить много ресурсов процессора (fx. Показывает длинный список элементов). обходной путь к этому - вызов {DebuggerDisplay()}, который является только одним дорогостоящим вызовом, и вы можете заставить этот метод возвращать все имена свойств, которые вам нужны. Также, если метод является частным, он технически нигде не используется и будет удален во время сборки Release. но отладчик все еще может использовать его во время отладки.

Jim Wolff 08.10.2018 14:11

Я бы посоветовал [TestFixture] и [Test] - из библиотеки nUnit.

Модульные тесты в вашем коде обеспечивают безопасность при рефакторинге и кодифицированной документации.

Мне нравится [DebuggerStepThrough] из System.Diagnostics.

Это очень удобно, чтобы избежать использования однострочных методов или свойств, которые ничего не делают (если вы вынуждены работать в раннем .Net без автоматических свойств). Поместите атрибут в короткий метод или в средство получения или установки свойства, и вы пролетите мимо, даже нажав «шаг в» в отладчике.

Так много раз я хотел бы знать об этой собственности

wusher 28.09.2008 07:23

Жаль, что он сломан из-за закрытия - см. gregbeech.com/blogs/tech/archive/2008/10/17/… для получения дополнительной информации.

Greg Beech 01.12.2008 05:33

Также полезно для любого кода WM_Paint, который, как вы знаете, работает :)

Pondidum 02.05.2009 16:56

@GregBeech Этот URL возвращает ошибку .NET. Классно! :)

smdrager 08.06.2012 16:44

@smdrager - Должно быть, это временная проблема, похоже, сегодня у меня работает.

Greg Beech 17.06.2012 13:37

[DebuggerHidden] - еще один хороший. Это заставляет выброшенные ошибки прерываться в вызывающем методе (для таких вещей, как обработчики БД)

Patrick 02.12.2014 16:58

Как разработчик среднего уровня мне нравится

System.ComponentModel.EditorBrowsableAttribute Позволяет мне скрывать свойства, чтобы разработчик пользовательского интерфейса не был перегружен свойствами, которые им не нужно видеть.

System.ComponentModel.BindableAttribute Некоторые вещи не нужно связывать с данными. Опять же, сокращает объем работы, необходимой разработчикам пользовательского интерфейса.

Мне также нравится DefaultValue, о котором упоминал Лоуренс Джонстон.

System.ComponentModel.BrowsableAttribute и Flags используются регулярно.

я использую System.STAThreadAttribute System.ThreadStaticAttribute при необходимости.

Кстати. Они не менее ценны для всех разработчиков .Net framework.

Чаще всего я использую атрибуты, связанные с сериализацией XML.

XmlRoot

XmlElement

XmlAttribute

так далее...

Чрезвычайно полезно при выполнении любого быстрого и грязного синтаксического анализа или сериализации XML.

Компилятор поддерживает только несколько атрибутов, но одно очень интересное использование атрибутов находится в AOP: PostSharp использует ваши индивидуальные атрибуты для внедрения IL в методы, позволяя использовать всевозможные возможности ... log / trace являются тривиальными примерами, но некоторые другие хорошие примеры такие вещи, как автоматическая реализация INotifyPropertyChanged (здесь).

Некоторые из них встречаются и напрямую влиять на компилятор или среду выполнения:

  • [Conditional("FOO")] - вызовы этого метода (включая оценку аргументов) происходят только в том случае, если во время сборки определен символ "FOO".
  • [MethodImpl(...)] - используется для обозначения некоторых вещей, таких как синхронизация, встраивание
  • [PrincipalPermission(...)] - используется для автоматической вставки проверок безопасности в код
  • [TypeForwardedTo(...)] - используется для перемещения типов между сборками без перестройки звонящих

Для вещей, которые проверяются вручную через отражение - я большой поклонник атрибутов System.ComponentModel; такие вещи, как [TypeDescriptionProvider(...)], [TypeConverter(...)] и [Editor(...)], которые могут полностью изменить поведение типов в сценариях привязки данных (например, динамические свойства и т. д.).

[TypeConverter(typeof(ExpandableObjectConverter))]

Сообщает дизайнеру расширить свойства, которые являются классами (вашего контроля)

[Obfuscation]

Дает указание средствам обфускации выполнять указанные действия для сборки, типа или элемента. (хотя обычно вы используете уровень сборки [assembly:ObfuscateAssemblyAttribute(true)]

Я догадался, но ошибся. Атрибут обфускации - это всего лишь подсказка для сторонних обфсукаторов. Это не заставляет компилятор что-либо скрывать по умолчанию.

Dan Is Fiddling By Firelight 04.01.2012 18:25

@DanNeely бесплатно для пользователей Visual Studio Pro / Ultimate!

Chris S 04.01.2012 19:23

Если вы имеете в виду DotFuscator Community Edition, уровень защиты настолько низок, что в лучшем случае он почти ни для чего не учитывается.

Dan Is Fiddling By Firelight 04.01.2012 19:39

@ricovox Я добавил резюме

Chris S 03.01.2013 18:54

[XmlIgnore]

поскольку это позволяет игнорировать (в любой сериализации xml) «родительские» объекты, которые в противном случае могли бы вызвать исключения при сохранении.

// on configuration sections
[ConfigurationProperty] 

// in asp.net
[NotifyParentProperty(true)]

какова цель NotifyParentProperty?

Maslow 05.01.2012 22:06

В последнее время пользуюсь [DataObjectMethod]. Он описывает метод, поэтому вы можете использовать свой класс с ObjectDataSource (или другими элементами управления).

[DataObjectMethod(DataObjectMethodType.Select)] 
[DataObjectMethod(DataObjectMethodType.Delete)] 
[DataObjectMethod(DataObjectMethodType.Update)] 
[DataObjectMethod(DataObjectMethodType.Insert)] 

Больше информации

В нашем текущем проекте мы используем

[ComVisible(false)]

Он контролирует доступность отдельного управляемого типа или члена или всех типов в сборке для COM.

Больше информации

Мне нравится использовать атрибут [ThreadStatic] в сочетании с программированием на основе потоков и стека. Например, если мне нужно значение, которым я хочу поделиться с остальной частью последовательности вызовов, но я хочу сделать это вне диапазона (т.е. вне параметров вызова), я могу использовать что-то вроде этого.

class MyContextInformation : IDisposable {
    [ThreadStatic] private static MyContextInformation current;

    public static MyContextInformation Current {
        get { return current; }
    }

    private MyContextInformation previous;


    public MyContextInformation(Object myData) {
       this.myData = myData;
       previous = current;
       current = this;
    }

    public void Dispose() {
       current = previous;
    }
}

Позже в своем коде я могу использовать это для внеполосного предоставления контекстной информации людям, находящимся ниже по течению от моего кода. Пример:

using(new MyContextInformation(someInfoInContext)) {
   ...
}

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

а как тогда получить доступ? Не понимаю смысла вашего образца использования здесь. Вы можете объяснить?

Beachwalker 21.08.2015 14:00

@Beachwalker Current должен быть статическим, отредактировал его сейчас. Теперь вы можете получить доступ к MyContextInformation.Current, чтобы получить активный контекст в стеке. Это то, что в некоторых случаях является очень хорошей концепцией, наш (моей компании) движок использует ее для множества целей.

Felix K. 04.01.2016 13:54

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

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Foo Bar {
    get { return baz; }
    set { baz = value; }
}

очень полезно для компонентов WinForms. использовать вместе с [Browsable (false)]

Mark Heath 09.11.2010 20:21

Хороший момент - [Browsable(false)] требуется, чтобы скрыть его от пользователя разработчика, тогда как [DesignerSerializationVisibility(DesignerSerializationVisibi‌​lity.Hidden)] требуется, чтобы он не был сериализован.

configurator 09.11.2010 20:46

Я всегда использую атрибуты DisplayName, Description и DefaultValue поверх общедоступных свойств моих пользовательских элементов управления, настраиваемых элементов управления или любого класса, который я редактирую через сетку свойств. Эти теги используются .NET PropertyGrid для форматирования имени, панели описания и значений, выделенных жирным шрифтом, для которых не заданы значения по умолчанию.

[DisplayName("Error color")]
[Description("The color used on nodes containing errors.")]
[DefaultValue(Color.Red)]
public Color ErrorColor
{
    ...
} 

Я просто хочу, чтобы IntelliSense в Visual Studio учла атрибут Description, если XML-комментарий не найден. Это позволило бы избежать повторения одного и того же предложения дважды.

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

nawfal 09.06.2013 12:05

[System.Security.Permissions.PermissionSetAttribute] позволяет применять меры безопасности для PermissionSet к коду с использованием декларативной безопасности.

// usage:
public class FullConditionUITypeEditor : UITypeEditor
{
    // The immediate caller is required to have been granted the FullTrust permission.
    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
    public FullConditionUITypeEditor() { }
}

Здесь - пост про интересный атрибут Внутреннее устройство. В основном то, что он делает, он имитирует функциональность доступа друзей C++. Это очень удобно для модульного тестирования.

Разве вы не имеете в виду удобство для взлома модульного теста на то, что нельзя / не нужно тестировать?

the_drow 13.07.2011 09:20

@the_drow: Вы говорите о «частных аксессуарах»: msdn.microsoft.com/en-us/library/ms184807%28v=vs.80%29.aspx

habakuk 12.07.2012 16:18

@habakuk: Не совсем. Есть случаи, когда внутренние классы должны быть представлены для модульного тестирования, обычно из-за плохого дизайна.

the_drow 12.07.2012 19:27

@the_drow: Я бы не сказал, что InternalsVisibleTo вреден для модульного тестирования; вы можете создавать и тестировать меньшие «юниты», которые не видны за пределами вашего проекта (это помогает вам иметь чистый и небольшой api). Но если вам нужны «частные аксессоры» для модульного тестирования, то, вероятно, что-то не так.

habakuk 13.07.2012 13:16

@habakuk: Если нужно протестировать, он должен быть общедоступным.

the_drow 13.07.2012 15:10

@the_drow Я не согласен с вашим утверждением, что internal не является общедоступным. Он общедоступен в тестируемой сборке и должен проходить модульное тестирование, чтобы другие классы в сборке могли предположить, что это функция исправления. Если вы его не тестируете, вам придется протестировать его функции во всех потребляющих классах.

tvanfosson 10.12.2012 18:53

Я бы проголосовал за Conditional

[Conditional("DEBUG")]
public void DebugOnlyFunction()
{
    // your code here
}

Вы можете использовать это, чтобы добавить функцию с расширенными функциями отладки; как и Debug.Write, он вызывается только в отладочных сборках и поэтому позволяет вам инкапсулировать сложную логику отладки вне основного потока вашей программы.

Разве это не то же самое, что делать #if DEBUG?

Neil N 11.08.2009 00:11

В некотором смысле, #if DEBUG означает, что вызывающий объект также не должен вызывать его, в то время как Conditioinal оставляет вызов, но делает его NOP, который удаляется при JIT.

Rangoric 14.03.2011 23:10

Кроме того, вы обычно используете #if DEBUG вокруг звонки и [Conditional] вокруг методы. Поэтому, если вы вызываете метод отладки 100 раз, его отключение зависит от одного изменения кода, а не 100 раз.

Steve Cooper 15.03.2011 14:46

Комментарий Рангорика несколько неверен (по крайней мере, для C#): метод включен без изменений; сам сайт вызова опускается. Это имеет несколько последствий: параметры не оцениваются, а условный метод содержится в выводе компилятора без изменений. Вы можете убедиться в этом с помощью рефлексии. msdn.microsoft.com/en-us/library/aa664622.aspxblogs.msdn.com/b/jmstall/archive/2007/10/15/…

Mark Sowul 03.10.2012 00:06

Он плохо назван, плохо поддерживается во фреймворке и не требует параметра, но этот атрибут является полезным маркером для неизменяемых классов:

[ImmutableObject(true)]

Согласно документации, используется только во время разработки (к сожалению).

Hans Kesting 16.09.2009 17:35

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

Roy Tinker 05.03.2014 04:33

[DeploymentItem("myFile1.txt")]Документ MSDN по DeploymentItem

Это действительно полезно, если вы тестируете файл или используете файл в качестве входных данных для вашего теста.

Я генерирую класс сущности данных через CodeSmith и использую атрибуты для некоторой процедуры проверки. Вот пример:

/// <summary>
/// Firm ID
/// </summary>
[ChineseDescription("送样单位编号")]
[ValidRequired()]
public string FirmGUID
{
    get { return _firmGUID; }
    set { _firmGUID = value; }
}

И у меня есть служебный класс для проверки на основе атрибутов, прикрепленных к классу сущности данных. Вот код:

namespace Reform.Water.Business.Common
{
/// <summary>
/// Validation Utility
/// </summary>
public static class ValidationUtility
{
    /// <summary>
    /// Data entity validation
    /// </summary>
    /// <param name = "data">Data entity object</param>
    /// <returns>return true if the object is valid, otherwise return false</returns>
    public static bool Validate(object data)
    {
        bool result = true;
        PropertyInfo[] properties = data.GetType().GetProperties();
        foreach (PropertyInfo p in properties)
        {
            //Length validatioin
            Attribute attribute = Attribute.GetCustomAttribute(p,typeof(ValidLengthAttribute), false);
            if (attribute != null)
            {
                ValidLengthAttribute validLengthAttribute = attribute as ValidLengthAttribute;
                if (validLengthAttribute != null)
                {
                    int maxLength = validLengthAttribute.MaxLength;
                    int minLength = validLengthAttribute.MinLength;
                    string stringValue = p.GetValue(data, null).ToString();
                    if (stringValue.Length < minLength || stringValue.Length > maxLength)
                    {
                        return false;
                    }
                }
            }
            //Range validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRangeAttribute), false);
            if (attribute != null)
            {
                ValidRangeAttribute validRangeAttribute = attribute as ValidRangeAttribute;
                if (validRangeAttribute != null)
                {
                    decimal maxValue = decimal.MaxValue;
                    decimal minValue = decimal.MinValue;
                    decimal.TryParse(validRangeAttribute.MaxValueString, out maxValue);
                    decimal.TryParse(validRangeAttribute.MinValueString, out minValue);
                    decimal decimalValue = 0;
                    decimal.TryParse(p.GetValue(data, null).ToString(), out decimalValue);
                    if (decimalValue < minValue || decimalValue > maxValue)
                    {
                        return false;
                    }
                }
            }
            //Regex validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRegExAttribute), false);
            if (attribute != null)
            {
                ValidRegExAttribute validRegExAttribute = attribute as ValidRegExAttribute;
                if (validRegExAttribute != null)
                {
                    string objectStringValue = p.GetValue(data, null).ToString();
                    string regExString = validRegExAttribute.RegExString;
                    Regex regEx = new Regex(regExString);
                    if (regEx.Match(objectStringValue) == null)
                    {
                        return false;
                    }
                }
            }
            //Required field validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRequiredAttribute), false);
            if (attribute != null)
            {
                ValidRequiredAttribute validRequiredAttribute = attribute as ValidRequiredAttribute;
                if (validRequiredAttribute != null)
                {
                    object requiredPropertyValue = p.GetValue(data, null);
                    if (requiredPropertyValue == null || string.IsNullOrEmpty(requiredPropertyValue.ToString()))
                    {
                        return false;
                    }
                }
            }
        }
        return result;
    }
}
}

Внезапно, вот краткий список, примерно отсортированный по частоте использования, предопределенных атрибутов, которые я действительно использую в большом проекте (~ 500k LoC):

Флаги, Сериализуемый, WebMethod, COMVisible, TypeConverter, Conditional, ThreadStatic, Obsolete, InternalsVisibleTo, DebuggerStepThrough.

+1 для ThreadStatic, удивлен, что никто не упомянул об этом до сих пор, а также для статистического подхода

staafl 01.10.2013 01:42

[EditorBrowsable(EditorBrowsableState.Never)] позволяет скрыть свойства и методы от IntelliSense, если проект отсутствует в вашем решении. Очень полезно для сокрытия недопустимых потоков для свободных интерфейсов. Как часто вы хотите использовать GetHashCode () или Equals ()?

Для MVC [ActionName("Name")] позволяет вам иметь действия Get и Post с одной и той же сигнатурой метода или использовать тире в имени действия, что в противном случае было бы невозможно без создания для него маршрута.

Я всегда использую атрибуты, [Serializable], [WebMethod], [DefaultValue], [Description("description here")].

но кроме этого в C# есть Глобальные атрибуты.

[assembly: System.CLSCompliant(true)]
[assembly: AssemblyCulture("")]
[assembly: AssemblyDescription("")]

Я считаю важным упомянуть здесь, что следующие атрибуты также очень важны:

STAThreadAttribute 

Указывает, что модель потоков COM для приложения является однопоточным подразделением (STA).

Например, этот атрибут используется в приложениях Windows Forms:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

А также ...

SuppressMessageAttribute

Подавляет сообщение о конкретном нарушении правил инструмента статического анализа, разрешая множественное подавление одного артефакта кода.

Например:

[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isChecked")]
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "fileIdentifier")]
static void FileNode(string name, bool isChecked)
{
    string fileIdentifier = name;
    string fileName = name;
    string version = String.Empty;
}

Используется ли STAThread для предотвращения случайного запуска вашего приложения другим экземпляром при запуске?

Luminous 10.09.2014 16:51

DebuggerHiddenAttribute, который позволяет избежать ввода кода, который не следует отлаживать.

public static class CustomDebug
{
    [DebuggerHidden]
    public static void Assert(Boolean condition, Func<Exception> exceptionCreator) { ... }
}

...

// The following assert fails, and because of the attribute the exception is shown at this line
// Isn't affecting the stack trace
CustomDebug.Assert(false, () => new Exception()); 

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

[DebuggerHidden]
public Element GetElementAt(Vector2 position)
{
    return GetElementAt(position.X, position.Y);
}

public Element GetElementAt(Single x, Single y) { ... }

Если теперь вы вызываете GetElementAt(new Vector2(10, 10)) и в обернутом методе возникает ошибка, стек вызовов не показывает метод, который вызывает метод, который вызывает ошибку.

Другие вопросы по теме