📜  C#-属性

📅  最后修改于: 2020-12-28 05:12:36             🧑  作者: Mango


属性是一个声明性标签,用于向运行时传达有关程序中各种元素(例如类,方法,结构,枚举器,程序集等)的行为的信息。您可以使用属性将声明性信息添加到程序中。声明性标记由放置在其所使用元素上方的方括号([])表示。

属性用于将元数据(例如编译器指令)和其他信息(例如注释,描述,方法和类)添加到程序。 .Net Framework提供了两种类型的属性:预定义属性和自定义生成的属性。

指定属性

指定属性的语法如下-

[attribute(positional_parameters, name_parameter = value, ...)]
element

在将属性应用于元素之前,在方括号内指定属性名称及其值。位置参数指定基本信息,名称参数指定可选信息。

预定义属性

.Net Framework提供了三个预定义的属性-

  • AttributeUsage
  • 有条件的
  • 过时的

AttributeUsage

预定义的属性AttributeUsage描述如何使用自定义属性类。它指定可以应用属性的项目类型。

指定此属性的语法如下-

[AttributeUsage (
   validon,
   AllowMultiple = allowmultiple,
   Inherited = inherited
)]

哪里,

  • 参数validon指定可以在其上放置属性的语言元素。它是枚举数AttributeTargets的值的组合。默认值为AttributeTargets.All

  • 参数allowmultiple (可选)为该属性的AllowMultiple属性提供一个布尔值。如果为真,则该属性为多用途。默认值为false(单次使用)。

  • 继承的参数(可选)为该属性的Inherited属性提供值,即布尔值。如果为true,则该属性由派生类继承。默认值为false(不继承)。

例如,

[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property, 
   AllowMultiple = true)]

有条件的

此预定义属性标记条件方法,其执行取决于指定的预处理标识符。

它将导致方法调用的条件编译,具体取决于诸如DebugTrace的指定值。例如,它在调试代码时显示变量的值。

指定此属性的语法如下-

[Conditional(
   conditionalSymbol
)]

例如,

[Conditional("DEBUG")]

以下示例演示了属性-

#define DEBUG
using System;
using System.Diagnostics;

public class Myclass {
   [Conditional("DEBUG")]
   
   public static void Message(string msg) {
      Console.WriteLine(msg);
   }
}
class Test {
   static void function1() {
      Myclass.Message("In Function 1.");
      function2();
   }
   static void function2() {
      Myclass.Message("In Function 2.");
   }
   public static void Main() {
      Myclass.Message("In Main function.");
      function1();
      Console.ReadKey();
   }
}

编译并执行上述代码后,将产生以下结果-

In Main function
In Function 1
In Function 2

过时的

此预定义的属性标记了不应使用的程序实体。它使您可以通知编译器放弃特定的目标元素。例如,当在类中使用新方法时,如果您仍想在该类中保留旧方法,则可以通过显示一条消息,指出应该使用新方法代替旧方法,将其标记为过时。

指定此属性的语法如下-

[Obsolete (
   message
)]

[Obsolete (
   message,
   iserror
)]

哪里,

  • 参数message是一个字符串,描述该项目过时的原因以及使用什么代替。

  • 参数iserror是一个布尔值。如果其值为true,则编译器应将该项的使用视为错误。默认值为false(编译器会生成警告)。

以下程序演示了这一点-

using System;

public class MyClass {
   [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
   
   static void OldMethod() {
      Console.WriteLine("It is the old method");
   }
   static void NewMethod() {
      Console.WriteLine("It is the new method"); 
   }
   public static void Main() {
      OldMethod();
   }
}

当您尝试编译程序时,编译器会显示一条错误消息,指出-

Don't use OldMethod, use NewMethod instead

创建自定义属性

.Net Framework允许创建自定义属性,这些自定义属性可用于存储声明性信息并可以在运行时进行检索。根据设计标准和应用需求,该信息可以与任何目标元素相关。

创建和使用定制属性涉及四个步骤-

  • 声明自定义属性
  • 构造自定义属性
  • 将定制属性应用于目标程序元素
  • 通过反射访问属性

最后一步涉及编写一个简单的程序以通读元数据以查找各种符号。元数据是有关数据或用于描述其他数据的信息的数据。该程序应使用反射在运行时访问属性。我们将在下一章中讨论。

声明自定义属性

新的自定义属性应该从System.Attribute类派生。例如,

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

public class DeBugInfo : System.Attribute

在前面的代码中,我们声明了一个名为DeBugInfo的自定义属性。

构造自定义属性

让我们构造一个名为DeBugInfo的自定义属性,该属性存储通过调试任何程序获得的信息。让它存储以下信息-

  • 错误的代码号
  • 识别错误的开发人员名称
  • 上次审核代码的日期
  • 用于存储开发人员评论的字符串消息

DeBugInfo类具有用于存储前三个信息的三个私有属性和用于存储消息的公共属性。因此,错误编号,开发人员的姓名和检查日期是DeBugInfo类的位置参数,消息是可选的或命名的参数。

每个属性必须至少具有一个构造函数。位置参数应通过构造函数传递。以下代码显示DeBugInfo类-

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

public class DeBugInfo : System.Attribute {
   private int bugNo;
   private string developer;
   private string lastReview;
   public string message;
   
   public DeBugInfo(int bg, string dev, string d) {
      this.bugNo = bg;
      this.developer = dev;
      this.lastReview = d;
   }
   public int BugNo {
      get {
         return bugNo;
      }
   }
   public string Developer {
      get {
         return developer;
      }
   }
   public string LastReview {
      get {
         return lastReview;
      }
   }
   public string Message {
      get {
         return message;
      }
      set {
         message = value;
      }
   }
}

应用自定义属性

通过将属性直接放置在目标之前来应用该属性-

[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
   //member variables
   protected double length;
   protected double width;
   public Rectangle(double l, double w) {
      length = l;
      width = w;
   }
   [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
   
   public double GetArea() {
      return length * width;
   }
   [DeBugInfo(56, "Zara Ali", "19/10/2012")]
   
   public void Display() {
      Console.WriteLine("Length: {0}", length);
      Console.WriteLine("Width: {0}", width);
      Console.WriteLine("Area: {0}", GetArea());
   }
}

在下一章中,我们使用反射类对象检索属性信息。