English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

دليل أساسي لتعليمات C#

دليل متقدم لتعليمات C#

C# تعليمات هندسية

الصفة بلغة C# (Attribute)

الخصائص (Attribute)هي تعليمات تهدف إلى نقل معلومات سلوك العناصر المختلفة (مثل الفئات، والأساليب، والهياكل، والقوائم، والمكونات، إلخ) عند تشغيل البرنامج. يمكنك إضافة معلومات تعريفيه إلى البرنامج باستخدام الخاصية. يتم وصف التعليمات التعبيرية بالبكرات المزدوجة [ ] التي تُوضع أمام العنصر الذي تطبق عليه.

تستخدم الخاصية (Attribute) لضيف بيانات النصوص، مثل تعليمات المبرمج، والتعليقات، والأساليب، والفئات، وغيرها من المعلومات. يقدم .Net framework نوعين من الخصائص:المحددة مسبقًاوالخصائصمخصصةالخصائص.

الخصائص (Attribute)

النحو الخاص بالخصائص (Attribute) كما يلي:

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

تحدد اسم الخاصية والقيمة في البكرات المزدوجة، وتوضع قبل العنصر الذي تطبق عليه. يحدد positional_parameters المعلومات الضرورية، ويعين name_parameter المعلومات الاختيارية.

الخصائص المحددة مسبقًا (Attribute)

يقدم .Net framework ثلاثة أنواع من الخصائص المحددة مسبقًا:

  • AttributeUsage

  • Conditional

  • Obsolete

AttributeUsage

الخصائص المحددة مسبقًا AttributeUsage يصف كيفية استخدام فئة خاصية مخصصة. يحدد النوع من المشاريع التي يمكن تطبيق الخاصية عليها.

指定该特性的语法如下:

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

其中:

  • يحدد المعامل validon العناصر اللغوية التي يمكن وضع الخاصية عليها. إنه معادلة AttributeTargets مجموع القيم من. AttributeTargets.All.

  • 参数 allowmultiple(اختياريًا) الخاصية AllowMultiple يقدم الخصائص (property) قيمة منطقية. إذا كانت صحيحة، فإن الخاصية متعددة الاستخدامات. القيمة الافتراضية هي false (استخدام واحد فقط).

  • 参数 inherited(اختياريًا) الخاصية Inherited يقدم الخصائص (property) قيمة منطقية. إذا كانت صحيحة، فإن الخاصية يمكن أن تورث من الفئة المشتقة. القيمة الافتراضية هي false (لا تورث).

例如:

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

这个预定义特性标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为 obsolete(过时的)。

指定该特性的语法如下:

[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

创建自定义特性(Attribute)

.Net 框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关。

创建并使用自定义特性包含四个步骤:

  • 声明自定义特性

  • 构建自定义特性

  • 在目标程序元素上应用自定义特性

  • 通过反射访问特性

最后一个步骤包含编写一个简单的程序来读取元数据以便查找各种符号。元数据是用于描述其他数据的数据和信息。该程序应使用反射来在运行时访问特性。我们将在下一章详细讨论这点。

声明自定义特性

一个新的自定义特性应派生自 System.Attribute 类。例如:

// 一个自定义特性 BugFix 被赋给类及其成员
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Methodُ|}}
AttributeTargets.Property,
AllowMultipleُ=ُtrue)]
publicُclassُDeBugInfoُ:ُSystem.Attribute

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

构建自定义特性

让我们构建一个名为 DeBugInfo 的自定义特性,该特性将存储调试程序获得的信息。它存储下面的信息:

  • bug 的代码编号

  • 辨认该 bug 的开发人员名字

  • 最后一次审查该代码的日期

  • 一个存储了开发人员标记的字符串消息

我们的 DeBugInfo 类将带有三个用于存储前三个信息的私有属性(property)和一个用于存储消息的公有属性(property)。所以 bug 编号、开发人员名字和审查日期将是 DeBugInfo 类的必需的定位( positional)参数,消息将是一个可选的命名(named)参数。

每个特性必须至少有一个构造函数。必需的定位( positional)参数应通过构造函数传递。下面的代码演示了 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ُرقمُالخطأ;
      }
  }
  publicُStringُDeveloper
  {
      get
      {
          returnُمطور;
      }
  }
  publicُStringُLastReview
  {
      get
      {
          returnُآخرمراجعة;
      }
  }
  publicُStringُMessage
  {
      get
      {
          returnُmessage;
      }
      set
      {
          messageُ=ُvalue;
      }
  }
}

تطبيقُالخصائصُالمخصصة

تطبيقُالخصائصُبوضعهاُقبلُالهدفُالقريبُمنها،ُل تطبيقُالخصائصُهذه

[DeBugInfo(45,ُ"زارة علي",ُ"12/8/2012"،Messageُ=ُ"نوع العودة غير مطابق")]
[DeBugInfo(49,ُ"نوها علي",ُ"10/10/2012"،Messageُ=ُ"مغير استعمال متغير غير مستخدم")]
classُمربع
{
  //ُم変iablesُالأعضاء
  protectedُطول;
  protectedُعرض;
  publicُمربع(doubleُl,ُdoubleُw)
  {
      طولُ=ُl;
      عرضُ=ُw;
  }
  [DeBugInfo(55,ُ"زارة علي",ُ"19/10/2012",
  Messageُ=ُ"نوع العودة غير مطابق")]
  publicُدوبرGetArea()
  {
      returnُطول * عرض;
  }
  [DeBugInfo(56, "Zara Ali", "19/10/2012")]
  public void Display()
  {
      Console.WriteLine("الطول: {0}", length);
      Console.WriteLine("العرض: {0}", width);
      Console.WriteLine("المنطقة: {0}", GetArea());
  }
}

في الفصل التالي، سنستخدم كائن Reflection للحصول على هذه المعلومات.