.NET中的Attribute(一)----认识

也许以我的水平在园子里写技术文章完全是班门弄斧了,我只是作为初学者记录下自己学习的历程金额总结,以便为以后的无为找到一个合适的借口。有什么不正确的地方请各位指出,不胜感激!

相信大家在看我的web.config配置文件的文章的时候还记得ConfigurationProperty这个类吧,它出现在指定元素(那里是配置节点对应的定义的属性(Property)上,用[]括起来)的上面,这里我们称之为Attribute(呵呵,又是一个“属性”)。
“属性”对所有.NET开发者来说再熟悉不过,在.NET中有两个“属性”(我觉得者完全是翻译的问题,虽然都是“属性”,但是它们有者本质的不同):Attribute和Property。下面我来谈谈我对它们的理解。

区别

本质的区别(个人观点哈^_^)是Attribute是类,而Property在类中是用来对成员定义的。(不知道这样说对不对)。看看MSDN对它们的定义吧:

Property:对于类的实现者,属性(Property)是一个或两个代码块,表示一个 get 访问器和/或一个 set 访问器。当读取属性(Property)时,执行 get 访问器的代码块;当向属性(Property)分配一个新值时,执行 set 访问器的代码块。不具有 set 访问器的属性(Property)被视为只读属性。不具有 get 访问器的属性(Property)被视为只写属性(Property)。同时具有这两个访问器的属性(Property)是读写属性(Property)。

Attribute:Attribute 类将预定义的系统信息或用户定义的自定义信息与目标元素相关联。目标元素可以是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性 (Property)、返回值、结构或其他属性 (Attribute)。

属性(Attribute)所提供的信息也称为元数据。元数据可由应用程序在运行时进行检查以控制程序处理数据的方式,也可以由外部工具在运行前检查以控制应用程序处理或维护自身的方式。例如,.NET Framework 预定义属性类型并使用属性类型控制运行时行为,某些编程语言使用属性类型表示 .NET Framework 公共类型系统不直接支持的语言功能。

有点感觉了,所以说两个“属性”是有本质的区别的。首先,Property是一个代码快,里面有一个get和/或set访问器,而Attribute是一个类,它将某些定制信息和目标元素关联,相当与把Attribute里定义的信息绑定到目标元素上了,目的就是要控制目标元素的执行,位置是在目标元素的前面用[]括起来的。其次,Property在运行时被初始化,而Attribute类在编译是进行实例化,这一点又和普通类不同。

认识Attibute类

Attibute可以放置在几乎所有的声明中(但特定的Attibute只能用在特定的声明之上)。在语法上,属性的指定方法为:将括在方括号中的属性名置于其适用的实体声明之前。
在dudu老大的《Attribute在.Net编程的应用》指出,将Attribute类作为编译器将不受数量的限制,而系统中的如#DEBUG,#IF,#ENDIF等专属C#,数量有限。如:
(这些是.NET内置的Attribute类)
Conditional:起条件编译的作用,只有满足条件,才允许编译器对它的代码进行编译。一般在程序调试的时候使用。
DllImport:用来标记非.NET的函数,表明该方法在一个外部的DLL中定义。
Obsolete:这个属性用来标记当前的方法已经被废弃,不再使用了。
如下例(来自dudu老大的《Attribute在.Net编程的应用》)
#define DEBUG //这里定义条件
   
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
   
namespace AttributeDemo
{
   class MainProgramClass
   {
 
      [DllImport("User32.dll")]
      public static extern int MessageBox(int hParent, string Message, string Caption, int Type);
    
      static void Main(string[] args)
      {
         DisplayRunningMessage();
         DisplayDebugMessage();
    
         MessageBox(0,"Hello","Message",0);
    
         Console.ReadLine();
      }
    
      [Conditional("DEBUG")]
      private static void DisplayRunningMessage()
      {
         Console.WriteLine("开始运行Main子程序。当前时间是"+DateTime.Now);
      }
 
      [Conditional("DEBUG")]
      [Obsolete]
      private static void DisplayDebugMessage()
      {
         Console.WriteLine("开始Main子程序");
      }
   }
}

如果在一个程序元素前面声明一个Attribute,那么就表示这个Attribute被施加到该元素上,前面的代码,[DllImport]施加到MessageBox函数上, [Conditional]施加到DisplayRuntimeMessage方法和DisplayDebugMessage方法,[Obsolete]施加到DisplayDebugMessage方法上。

根据上面涉及到的三个Attribute的说明,我们可以猜到程序运行的时候产生的输出:DllImport Attribute表明了MessageBox是User32.DLL中的函数,这样我们就可以像内部方法一样调用这个函数。

说明:(from msdn)
1、Attribute是有参数的,而这些参数可以是定位(未命名)参数也可以是命名参数。任何定位参数都必须按特定顺序指定并且不能省略,而命名参数是可选的且可以按任意顺序指定。首先指定定位参数。例如,这三个属性是等效的:
[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
第一个参数(DLL 名称)是定位参数并且总是第一个出现,其他参数为命名参数。在这种情况下,两个命名参数均默认为 false,因此可将其省略。如上所示。
2、在一个声明中可以放置多个属性,可分开放置,也可放在同一组括号中:
如:
void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }
3、某些属性对于给定实体可以指定多次。例如,Conditional 就是一个可多次使用的属性:
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
    // ...
}

请注意:根据约定,所有属性名称都以单词“Attribute”结束,以便将它们与“.NET Framework”中的其他项区分。但是,在代码中使用属性时不需要指定属性后缀。例如,[DllImport] 虽等效于 [DllImportAttribute],但 DllImportAttribute 才是该属性在 .NET Framework 中的实际名称。

好了,由于我的文笔不好,加上自己的理解不知道对不对,希望大家给我意见!

后面的文章我会以我的理解继续介绍对Attribute类的深入理解,并自定义自己的Attribute类。

posted on 2008-03-18 02:33  Austin Bai  阅读(588)  评论(1编辑  收藏  举报

导航