主页
  • 主页
  • 分类
  • 热文
  • 教程
  • 面试
  • 标签
C#

C# 基础

C# 主页
C# 概述
C# 环境
C# 程序结构
C# 基本语法
C# 数据类型
C# 类型转换
C# 变量
C# 常量
C# 运算符
C# 决策结构
C# 循环结构
C# 封装
C# 方法
C# 可空类型
C# 数组
C# 字符串
C# 结构体
C# 枚举
C# 类
C# 继承
C# 多态性
C# 操作符重载
C# 接口
C# 命名空间
C# 预处理
C# 正则表达式
C# 异常
C# 文件与流

C# 高级

C# 属性(Attributes)
C# 反射
C# 属性(Properties)
C# 索引器
C# 委托
C# 事件
C# 集合
C# 泛型
C# 匿名方法
C# 不安全代码
C# 线程

基础

C# 主页
C# 概述
C# 环境
C# 程序结构
C# 基本语法
C# 数据类型
C# 类型转换
C# 变量
C# 常量
C# 运算符
C# 决策结构
C# 循环结构
C# 封装
C# 方法
C# 可空类型
C# 数组
C# 字符串
C# 结构体
C# 枚举
C# 类
C# 继承
C# 多态性
C# 操作符重载
C# 接口
C# 命名空间
C# 预处理
C# 正则表达式
C# 异常
C# 文件与流

高级

C# 属性(Attributes)
C# 反射
C# 属性(Properties)
C# 索引器
C# 委托
C# 事件
C# 集合
C# 泛型
C# 匿名方法
C# 不安全代码
C# 线程

C# 属性(Attributes)


上一章 下一章

属性

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

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

指定属性

指定属性的语法如下:

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

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

预定义属性

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

  • AttributeUsage
  • Conditional
  • Obsolete

AttributeUsage

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

指定此属性的语法如下:

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

其中,

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

  • 参数 allowmultiple(可选)为此属性的 AllowMultiple 属性提供了值,这是一个布尔值。如果这是真的,属性是多用途的。默认值是假(单用途)。

  • 参数 inherited(可选)为此属性的 Inherited 属性提供了值,这是一个布尔值。如果是真的,属性由派生类继承。默认值是假(不继承)。

例如,

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

Conditional

这个预定义的属性标记了一个其执行依赖于指定预处理标识符的条件方法。

它根据指定的值(如 Debug 或 Trace)导致方法调用的条件编译。例如,它在调试代码时显示变量的值。

指定此属性的语法如下:

[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("在函数 1 中。");
      function2();
   }
   static void function2() {
      Myclass.Message("在函数 2 中。");
   }
   public static void Main() {
      Myclass.Message("在主函数中。");
      function1();
      Console.ReadKey();
   }
}

当上述代码被编译和执行时,它产生以下结果:

在主函数中
在函数 1 中
在函数 2 中

Obsolete

这个预定义的属性标记了一个不应被使用的程序实体。它使你能够通知编译器丢弃特定的目标元素。例如,当类中正在使用一个新的方法,并且如果你想保留类中的旧方法,你可以标记它为过时,并显示一条消息建议使用新的方法而不是旧的方法。

指定此属性的语法如下:

[Obsolete (
   message)
]

[Obsolete (
   message,
   iserror)
]

其中,

  • 参数 message 是一个字符串,描述了为什么该元素过时以及应使用什么代替。

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

下面的程序演示了这一点:

using System;

public class MyClass {
   [Obsolete("不要使用 OldMethod,使用 NewMethod 代替", true)]
   
   static void OldMethod() {
      Console.WriteLine("这是旧方法");
   }
   static void NewMethod() {
      Console.WriteLine("这是新方法"); 
   }
   public static void Main() {
      OldMethod();
   }
}

当你尝试编译程序时,编译器会给出一个错误信息:

不要使用 OldMethod,使用 NewMethod 代替

创建自定义属性

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

创建和使用自定义属性涉及四个步骤:

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

最后一个步骤涉及编写一个简单的程序来读取元数据以找到各种标记。元数据是关于数据的数据或用于描述其他数据的信息。此程序应在运行时使用反射来访问属性。我们将在下一章讨论这一点。

声明自定义属性

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

// 自定义属性 BugFix 用于分配给类及其成员
[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)
]

public class DeBugInfo : System.Attribute

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

构造自定义属性

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

  • 虫子的代码编号
  • 识别虫子的开发人员的名字
  • 最后一次代码审查的日期
  • 存储开发人员备注的字符串消息

DeBugInfo 类有三个私有属性用于存储前三条信息,并有一个公共属性用于存储消息。因此,虫子编号、开发人员的名字和审查日期是 DeBugInfo 类的位置参数,而消息是一个可选的或命名参数。

每个属性至少应该有一个构造函数。位置参数应该通过构造函数传递。下面的代码展示了 DeBugInfo 类:

// 自定义属性 BugFix 用于分配给类及其成员
[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 = "返回类型不匹配")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "未使用的变量")]
class Rectangle {
   // 成员变量
   protected double length;
   protected double width;
   public Rectangle(double l, double w) {
      length = l;
      width = w;
   }
   [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "返回类型不匹配")]
   
   public double GetArea() {
      return length * width;
   }
   [DeBugInfo(56, "Zara Ali", "19/10/2012")]
   
   public void Display() {
      Console.WriteLine("长度: {0}", length);
      Console.WriteLine("宽度: {0}", width);
      Console.WriteLine("面积: {0}", GetArea());
   }
}
上一章 下一章
阅读号二维码

关注阅读号

联系二维码

联系我们

© 2024 Yoagoa. All rights reserved.

粤ICP备18007391号

站点地图