最有用的属性

时间:2008-09-28 00:16:09

标签: c# .net .net-attributes

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

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

32 个答案:

答案 0 :(得分:655)

在调试期间将鼠标悬停在Type的实例上时,

[DebuggerDisplay]对于快速查看Type的自定义输出非常有用。例如:

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

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

alt text

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

答案 1 :(得分:261)

在我看来,

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

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

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

答案 2 :(得分:198)

[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"

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

答案 3 :(得分:174)

我喜欢[DebuggerStepThrough] from System.Diagnostics

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

答案 4 :(得分:133)

对于它的价值,这里是a list of all .NET attributes。有几百个。

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

答案 5 :(得分:127)

我的投票将是[Conditional]

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

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

答案 6 :(得分:96)

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

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

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

答案 7 :(得分:67)

[Serializable]一直用于将对象序列化和反序列化到外部数据源(如xml)或从远程服务器反序列化。 More about it here.

答案 8 :(得分:56)

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

答案 9 :(得分:44)

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

答案 10 :(得分:43)

我发现[DefaultValue]非常有用。

答案 11 :(得分:27)

我建议来自nUnit[TestFixture][Test]

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

答案 12 :(得分:25)

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

[ImmutableObject(true)]

答案 13 :(得分:25)

[XmlIgnore]

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

答案 14 :(得分: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;
    }
}

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

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

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

答案 15 :(得分: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()); 

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

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

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

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

答案 16 :(得分:21)

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

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

答案 17 :(得分:17)

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

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

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

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

答案 18 :(得分:15)

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

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

More info

答案 19 :(得分:14)

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

 [Serializable]
 [WebMethod]

答案 20 :(得分:11)

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

[ComVisible(false)]

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

More Info

答案 21 :(得分:11)

[TypeConverter(typeof(ExpandableObjectConverter))]

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

[Obfuscation]

Instructs obfuscation tools to take the specified actions for an assembly, type, or member.(虽然通常使用汇编级别[assembly:ObfuscateAssemblyAttribute(true)]

答案 22 :(得分:8)

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

XmlRoot

XmlElement

XmlAttribute

等...

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

答案 23 :(得分:8)

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

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

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

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

System.ComponentModel.BrowsableAttributeFlags会定期使用。

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

顺便说一下。对于所有.Net框架开发人员来说,这些都是有价值的。

答案 24 :(得分:8)

如果项目不在您的解决方案中,

[EditorBrowsable(EditorBrowsableState.Never)]允许您隐藏IntelliSense中的属性和方法。对于隐藏流畅接口的无效流非常有用。你多久想要GetHashCode()或Equals()?

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

答案 25 :(得分:7)

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

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

答案 26 :(得分:7)

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

STAThreadAttribute 

表示应用程序的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());
    }
}

还有......

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;
}

答案 27 :(得分:6)

[DeploymentItem("myFile1.txt")] MSDN Doc on DeploymentItem

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

答案 28 :(得分:6)

我通过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;
    }
}
}

答案 29 :(得分: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() { }
}

答案 30 :(得分:2)

// on configuration sections
[ConfigurationProperty] 

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

答案 31 :(得分:2)

我总是使用属性, [Serializable][WebMethod][DefaultValue][Description("description here")]

但除此之外,c#中有Global Attributes

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