C#属性及其用途

时间:2010-07-07 17:24:45

标签: c# attributes

我真的不太了解C#中的属性,我已经看到它们在很多不同的方式/地方使用,但我不认为我看到其中一些的重要性。一些肯定具有重要性,因为它们提供了显着的功能,例如[Serializable]。然而,其他人似乎并不那么重要,例如我的同事使用[DataMember]来标记属性。

我想我的问题是,什么是属性以及它们如何有用?有没有办法创建自己的属性,如何判断字段/方法/类/是否具有特定属性或在这些属性中设置了什么值?

4 个答案:

答案 0 :(得分:20)

  

属性是什么?

属性使您能够在描述该类型或方法的元数据中嵌入有关类型或方法的信息。

You typically want to use attributes to describe facts about the mechanism of the type or method rather than the meaning of the type or method.例如,假设您有一个类型Employee。关于Employee的含义的一个事实是它是一种Person,Employee有一个Manager,依此类推。关于Employee的机制的一个事实是它可以是数据绑定的目标,或者它可以被序列化为磁盘,或者其他什么。员工无法序列化为磁盘,但员工可以。通过属性,您可以从语义模型中分离有关技术细节的信息。

  

有没有办法创建自己的属性?

是。创建一个扩展Attribute的类。按照惯例,您希望将其命名为“FooAttribute”。如果这样做,您可以自行决定使用[Foo]语法还是[FooAttribute]语法。

  

如何判断字段/方法/类/是否具有特定属性或在这些属性中设置了什么值?

在反射对象上使用GetCustomAttributes方法。

  

我应该在哪里阅读更多信息?

从属性教程开始:

http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

然后阅读C#规范第17章的所有内容。

答案 1 :(得分:7)

Attributes是一种可以将元数据与.NET中的类型相关联的方法。这允许您检查类型并获取与该类型的“运行时”信息分开的信息。

这非常有用。您提到了[Serializable],但其他简单示例包含许多System.ComponentModel类型,例如Description,属性网格使用它来“描述”属性,当您在设计师。由于属性的“描述”与程序中类型的行为(在运行时)并不真正相关,因此它不属于类。但是,当您在可视化设计器中编辑控件时,它非常方便,例如,查看属性的描述(或类别等)。属性是处理它的手段。

答案 2 :(得分:6)

我认为以下问题的答案将为您提供一些洞察力。

How do attribute classes work?

这是我提供的答案的转贴。

属性本质上是可以附加到代码的各个部分的元数据。然后,该元数据可以是interogate并影响某些操作的行为。

属性几乎可以应用于代码的每个方面。例如,属性可以在程序集级别关联,例如AssemblyVersion和AssemblyFileVersion属性,它们控制与程序集关联的版本号。

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

然后,可以将Serializable属性应用于类型声明,以将该类型标记为支持序列化。事实上,这个属性在CLR中具有特殊含义,实际上直接作为特殊指令存储在IL中的类型中,这被优化为存储为位标志,可以更有效地处理,有一些属性这种性质,称为伪自定义属性。

还可以将其他属性应用于方法,属性,字段,枚举,返回值等。通过查看此链接,您可以了解可以应用属性的可能目标 http://msdn.microsoft.com/en-us/library/system.attributetargets(VS.90).aspx

除此之外,您还可以定义自己的自定义属性,然后可以将这些属性应用于属性所针对的适用目标。然后在运行时,您的代码可以反映自定义属性中包含的值并采取适当的操作。

对于一个相当天真的例子,这只是为了举例:) 您可能希望编写一个持久性引擎,该引擎将自动将Classes映射到数据库中的表,并将Class的属性映射到表列。您可以从定义两个自定义属性开始

TableMappingAttribute
ColumnMappingAttribute

然后您可以将其应用于您的课程,例如我们有一个Person类

[TableMapping("People")]
public class Person
{
  [ColumnMapping("fname")]
  public string FirstName {get; set;}

  [ColumnMapping("lname")]
  public string LastName {get; set;}
}

当编译时,除了编译器发出自定义属性定义的附加元数据这一事实外,其他几乎没有受到影响。但是,您现在可以编写一个PersistanceManager,它可以动态检查Person类实例的属性,并将数据插入People表,将FirstName属性中的数据映射到fname列,将LastName属性映射到lname列。 / p>

关于属性实例的问题,不会为类的每个实例创建属性实例。 People的所有实例将共享TableMappingAttribute和ColumnMappingAttributes的相同实例。实际上,只有在第一次实际查询属性时才会创建属性实例。

答案 3 :(得分:0)

C#提供了一种定义声明性标记的机制,称为属性,您可以将其置于源代码中的某些实体上以指定其他信息。可以在运行时通过反射检索属性包含的信息。您可以使用预定义属性,也可以定义自己的自定义属性。

http://msdn.microsoft.com/en-us/library/aa288059%28v=VS.71%29.aspx