最有用的属性

wus*_*her 769 .net c# .net-attributes

我知道属性非常有用.有一些预定义的,例如,[Browsable(false)]它允许您在属性选项卡中隐藏属性.这是一个很好的解释属性的问题:.NET中的属性是什么?

您在项目中实际使用的预定义属性(及其命名空间)是什么?

Viv*_*vek 663

[DebuggerDisplay]在调试期间将鼠标悬停在Type的实例上时,可以非常有助于快速查看Type的自定义输出.例:

[DebuggerDisplay("FirstName={FirstName}, LastName={LastName}")]
class Customer
{
    public string FirstName;
    public string LastName;
}
Run Code Online (Sandbox Code Playgroud)

这是它应该在调试器中查看的方式:

替代文字

此外,值得一提的是,[WebMethod]具有CacheDuration属性集的属性可以避免不必要的Web服务方法的执行.

  • 哇,真的很高兴知道.我通常通过重写ToString来完成同样的事情,但这更好. (60认同)
  • 小心这一点,它会占用CPU中比ToString更大的块. (16认同)
  • @NikolaRadosavljević只会在调试过程中占用CPU电量 (4认同)
  • 您还可以使用它来显示方法的结果。如果方法(或属性获取)有副作用,这可能会导致非常混乱的调试体验。 (2认同)
  • @Nickolay Kondratyev:我不知道所有的细节,但你可以看看下面的网络服务最佳实践,它可以带你得出一些结论:http://blogs.msdn.com/b/jaredpar/archive/ 2011/03/18/debuggerdisplay属性条最佳practices.aspx (2认同)

Dan*_*ert 268

System.Obsolete在我看来,这是框架中最有用的属性之一.对不应再使用的代码发出警告的能力非常有用.我喜欢有办法告诉开发人员应该不再使用某些东西,以及有办法解释原因并指出更好/新的做事方式.

Conditional attribute对于调试使用来说,它也非常方便.它允许您在代码中添加方法以用于调试目的,这些方法在构建解决方案时不会被编译.

然后有很多特定于Web控件的属性我觉得很有用,但是那些更具体,并且在我发现的服务器控件开发之外没有任何用途.

  • 您可以将"true"作为参数之一传递给System.Obsolete,这会导致警告成为错误,从而破坏构建.显然,一旦清除了所有警告,就应该这样做.:) (50认同)
  • @plinth这是为了防止**新**代码使用该方法.如果方法被标记为过时,旧代码将保持二进制兼容,但如果抛出异常,它将停止工作.如果有人使用反射来绕过"Obsolte"旗帜,那么你会遇到更糟糕的问题...... (17认同)
  • 清除所有警告后,删除方法不是更好吗? (14认同)
  • @Pedro:有时你不能出于向后兼容的原因.如果它是私有的和未使用的,是的,删除它. (10认同)
  • @plinth由于许多原因抛出一个异常是个坏主意,#1是使用Obsolete()的主要原因是你可以在过渡阶段保持编译代码的工作.如果您不允许任何人调用该方法,为什么不删除它? (3认同)
  • @Dan - 如果你在编译集*上标记了失败并且出现错误,那么它就不应该*被调用.如果它在运行时被调用,那么有人违反了过时... (2认同)
  • 我写了一篇关于使用条件属性进行调试的文章.在某些情况下,我实际上更喜欢使用它们而不是断点.这里有一些例子...... http://www.codefromjames.com/wordpress/?p=131 (2认同)

Sho*_*og9 202

[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"
Run Code Online (Sandbox Code Playgroud)

Leppie指出了一些我没有意识到的东西,这反过来削弱了我对这个属性的热情:它并没有指示编译器允许位组合作为枚举变量的有效值,编译器允许枚举变量.我的C++背景显示...... 叹息

  • `[Flags]`确实比仅仅是语法糖更有用.使用Web服务时,如果像`SandwichStuff.Cheese |这样的值,则序列化/反序列化将不起作用 SandwichStuff.Ham | SandwichStuff.Jam`被传递.如果没有`[Flags]`属性,反序列化器将不知道该值可以是标志的组合.在花了大约两天的时间思考为什么我的WCF不能正常工作之后,学到了很多. (31认同)
  • 我希望你们都意识到Flags属性确实是bug.除了TypeConverter之外,根本不需要/使用它. (13认同)
  • @leppie:ToString()也是如此.但是......哇 出于某种原因,我一直期望没有属性的枚举行为与C++相同:或者值生成一个整数(不能按原样传递给期望枚举参数的方法).我现在看到的情况并非如此.弱......好吧,.NET枚举很糟糕. (3认同)
  • [Flags]实际上只能帮助调试器和.ToString()函数知道一个值可能是枚举中几个声明的组合.我不确定,它可能会让Intellisense帮助你更有效地使用枚举. (2认同)

Bla*_*rad 175

我喜欢[DebuggerStepThrough]System.Diagnostics.

避免单步执行那些单线无操作方法或属性非常方便(如果你被迫在没有自动属性的早期.Net中工作).将属性放在一个简短的方法或属性的getter或setter上,即使在调试器中点击"step into",你也会飞得很快.

  • 很多次,我希望我知道这个属性 (5认同)
  • 对于你知道的任何WM_Paint代码也很有用:) (3认同)

wpr*_*prl 134

对于它的价值,这里是所有.NET属性的列表.有几百个.

我不知道其他人,但我有一些严肃的RTFM要做!

  • 发布的列表是针对.net 1.1这里是3.5的列表http://msdn.microsoft.com/en-us/library/system.attribute.aspx(你需要向下滚动一点) (33认同)
  • 实际上,链接到最新,而不是3.5具体. (8认同)
  • 更新了问题中的链接.现在它是3.5的完整列表 (2认同)

Ste*_*per 127

我的投票将是 [Conditional]

[Conditional("DEBUG")]
public void DebugOnlyFunction()
{
    // your code here
}
Run Code Online (Sandbox Code Playgroud)

您可以使用它来添加具有高级调试功能的功能; 比如Debug.Write,它只在调试版本中调用,因此允许您将复杂的调试逻辑封装在程序的主流程之外.

  • 此外,您通常会在*calls*周围使用#if DEBUG,在*methods*周围使用[Conditional].因此,如果您将调试方法调用100次,则将其关闭只需更改一次代码,而不是100次. (23认同)
  • Rangoric的评论是巧妙的错误(至少对于C#而言):该方法未被修改; 呼叫站点本身被省略.这有一些含义:不评估参数,并且在编译器的输出中包含未修改的条件方法.您可以使用反射验证这一点.http://msdn.microsoft.com/en-us/library/aa664622.aspx http://blogs.msdn.com/b/jmstall/archive/2007/10/15/trivia-about-the-conditional-attribute的.aspx (13认同)
  • 有点,#if DEBUG意味着调用者也不必调用它,而Conditioinal离开调用但是使它成为一个在JIT被淘汰的NOP. (10认同)
  • 这和#if DEBUG一样吗? (5认同)

Ant*_*ien 97

我总是用DisplayName,DescriptionDefaultValue属性在我的用户控件,自定义控件,不然我会通过属性编辑网格中任何一类的公共属性..NET PropertyGrid使用这些标记来格式化未设置为默认值的名称,描述面板和粗体值.

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

我希望Description如果没有找到XML注释,Visual Studio的IntelliSense会考虑该属性.这样可以避免两次重复相同的句子.

  • 不相信没有人指出`描述`,直到你..当它与枚举一起使用时对我最有帮助.. (3认同)

Gil*_*gan 68

[Serializable]始终用于将对象序列化和反序列化到外部数据源(如xml)或从远程服务器反序列化.更多关于它的信息.


Chr*_*ham 57

在Hofstadtian精神中,该[Attribute]属性非常有用,因为它是您创建自己的属性的方式.我使用属性而不是接口来实现插件系统,向Enums添加描述,模拟多个调度和其他技巧.

  • 听起来很酷!您是否介意展示插件系统和枚举说明的一些示例?这些都是我有兴趣实现自己的事情! (13认同)

xro*_*ost 46

是关于有趣的属性InternalsVisibleTo的帖子.基本上它的作用是模仿C++朋友的访问功能.它非常方便单元测试.

  • @the_drow我不同意你的断言"内部`不公开.它在正在测试的程序集中是公共的,应该进行单元测试,以便程序集中的其他类可以承担它的更正功能.如果您不对它进行单元测试,则必须在所有消费类中测试其功能. (10认同)
  • 对于那些无法/不应该测试的东西进行单元测试,你是不是很方便? (7认同)
  • @the_drow:我不会说InternalsVisibleTo对于单元测试来说是邪恶的; 您可以创建和测试在项目外不可见的较小"单位"(它可以帮助您获得干净且小巧的api).但是,如果您需要"私人访问者"进行单元测试,可能会出现问题. (2认同)

Law*_*ton 43

我发现[DefaultValue]它非常有用.


Adr*_*ble 28

我建议[TestFixture][Test]- 来自nUnit库.

代码中的单元测试为重构和编码文档提供了安全性.


小智 26

[XmlIgnore]
Run Code Online (Sandbox Code Playgroud)

因为这允许你忽略(在任何xml序列化中)'父'对象,否则在保存时会导致异常.


Aja*_*axx 25

我喜欢将该[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;
    }
}
Run Code Online (Sandbox Code Playgroud)

稍后在我的代码中,我可以使用它来向我的代码下游的人提供带外的上下文信息.例:

using(new MyContextInformation(someInfoInContext)) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

ThreadStatic属性允许我将调用范围仅限于有问题的线程,避免跨线程的数据访问的混乱问题.


Nei*_*eil 25

它没有良好的名称,在框架中没有得到很好的支持,并且不需要参数,但是这个属性对于不可变类是一个有用的标记:

[ImmutableObject(true)]
Run Code Online (Sandbox Code Playgroud)

  • 根据文档,仅在设计时使用(不幸的是). (6认同)

Fel*_* K. 22

所述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()); 
Run Code Online (Sandbox Code Playgroud)

它还可以防止在堆栈跟踪中显示方法,当有一个只包装另一个方法的方法时很有用:

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

public Element GetElementAt(Single x, Single y) { ... }
Run Code Online (Sandbox Code Playgroud)

如果现在调用GetElementAt(new Vector2(10, 10))并且在包装方法中发生错误,则调用堆栈不会显示调用抛出错误的方法的方法.


con*_*tor 21

DesignerSerializationVisibilityAttribute非常有用.当您在控件或组件上放置运行时属性,并且您不希望设计器对其进行序列化时,您可以像这样使用它:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Foo Bar {
    get { return baz; }
    set { baz = value; }
}
Run Code Online (Sandbox Code Playgroud)

  • 对WinForms组件非常有用.与[Browsable(false)]一起使用 (4认同)
  • 好点 - "[Browsable(false)]`需要将它隐藏在设计者的用户手中,其中需要`[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]`,因此不会被序列化. (3认同)

Mar*_*ell 17

只有少数属性得到了编译器的支持,但是AOP中一个非常有趣的属性使用:PostSharp使用你的定制属性将IL注入到方法中,允许所有方式的能力......日志/跟踪是一个简单的例子 - 但是其他一些很好的例子像自动INotifyPropertyChanged实现(这里).

一些发生并直接影响编译器或运行时:

  • [Conditional("FOO")] - 只有在构建期间定义"FOO"符号时,才会调用此方法(包括参数评估)
  • [MethodImpl(...)] - 用于表示同步,内联等内容
  • [PrincipalPermission(...)] - 用于自动将安全检查注入代码
  • [TypeForwardedTo(...)]- 用于在程序集之间移动类型而不重建调用者

对于通过反射手动检查的东西 - 我是System.ComponentModel属性的忠实粉丝; 之类的东西[TypeDescriptionProvider(...)],[TypeConverter(...)]以及[Editor(...)]其可完全改变的类型的数据绑定方案的行为(即,动态特性等).


Fly*_*wat 15

如果我要进行代码覆盖爬行,我认为这两个将是顶级的:

 [Serializable]
 [WebMethod]
Run Code Online (Sandbox Code Playgroud)

  • [WebMethod]用于装饰在Web服务中公开的方法.[Serializable]标记您的对象,以便可以将它们序列化,以便在应用程序域中传递它们. (15认同)

wus*_*her 15

[DataObjectMethod]最近一直在使用.它描述了该方法,因此您可以将您的类与ObjectDataSource(或其他控件)一起使用.

[DataObjectMethod(DataObjectMethodType.Select)] 
[DataObjectMethod(DataObjectMethodType.Delete)] 
[DataObjectMethod(DataObjectMethodType.Update)] 
[DataObjectMethod(DataObjectMethodType.Insert)] 
Run Code Online (Sandbox Code Playgroud)

更多信息


Chr*_*s S 12

[TypeConverter(typeof(ExpandableObjectConverter))]
Run Code Online (Sandbox Code Playgroud)

告诉设计者扩展属性(属于您的控件)

[Obfuscation]
Run Code Online (Sandbox Code Playgroud)

指示模糊处理工具对程序集,类型或成员执行指定的操作.(尽管通常使用装配级别[assembly:ObfuscateAssemblyAttribute(true)]

  • 如果你指的是DotFuscator社区版,那么提供的保护级别是如此之低,以至于它几乎不计算任何东西. (4认同)

Ahm*_*med 12

在我们当前的项目中,我们使用

[ComVisible(false)]
Run Code Online (Sandbox Code Playgroud)

它控制单个托管类型或成员或程序集中所有类型的可访问性.

更多信息


Bra*_*non 9

我最常用的属性是与XML序列化相关的属性.

XmlRoot

XmlElement

XmlAttribute

等等...

在进行任何快速和脏的XML解析或序列化时非常有用.


ElG*_*nde 8

作为中间层开发人员,我喜欢

System.ComponentModel.EditorBrowsableAttribute 允许我隐藏属性,以便UI开发人员不会被他们不需要查看的属性所淹没.

System.ComponentModel.BindableAttribute有些东西不需要数据绑定.同样,减少了UI开发人员需要完成的工作.

我也喜欢DefaultValue劳伦斯约翰斯顿提到的那个.

System.ComponentModel.BrowsableAttributeFlags经常使用.

我需要 System.STAThreadAttribute System.ThreadStaticAttribute 时使用.

顺便说说.我对所有.Net框架开发人员都有同样的价值.


smd*_*ger 8

[EditorBrowsable(EditorBrowsableState.Never)]如果项目不在您的解决方案中,则允许您从IntelliSense隐藏属性和方法.对于隐藏流畅接口的无效流非常有用.你多久想要GetHashCode()或Equals()?

对于MVC [ActionName("Name")],您可以使用相同的方法签名获取Get动作和Post动作,或者在动作名称中使用破折号,否则在没有为其创建路径的情况下将无法使用破折号.


Eld*_*rum 7

在我的脑海中,这是一个快速列表,大致按使用频率排序,我在一个大项目中实际使用的预定义属性(~500k LoCs):

Flags,Serializable,WebMethod,COMVisible,TypeConverter,Conditional,ThreadStatic,Obsolete,InternalsVisibleTo,DebuggerStepThrough.

  • ThreadStatic的+1,令人惊讶的是到目前为止没有人提到它,也是统计方法 (2认同)

Eri*_*ura 7

我认为这里重要的是,以下属性也非常重要:

STAThreadAttribute 
Run Code Online (Sandbox Code Playgroud)

表示应用程序的COM线程模型是单线程单元(STA).

例如,在Windows窗体应用程序中使用此属性:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

并且 ...

SuppressMessageAttribute
Run Code Online (Sandbox Code Playgroud)

禁止报告特定的静态分析工具规则违规,允许对单个代码工件进行多次抑制.

例如:

[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;
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*ger 6

[DeploymentItem("myFile1.txt")] DeploymentItem上的MSDN Doc

如果您正在测试文件或使用该文件作为测试的输入,这非常有用.


小智 6

我通过CodeSmith生成数据实体类,并使用属性进行某些验证例程.这是一个例子:

/// <summary>
/// Firm ID
/// </summary>
[ChineseDescription("??????")]
[ValidRequired()]
public string FirmGUID
{
    get { return _firmGUID; }
    set { _firmGUID = value; }
}
Run Code Online (Sandbox Code Playgroud)

我有一个实用程序类,可以根据附加到数据实体类的属性进行验证.这是代码:

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;
    }
}
}
Run Code Online (Sandbox Code Playgroud)


CSh*_*per 5

[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() { }
}
Run Code Online (Sandbox Code Playgroud)