Share via


常用特性(C# 和 Visual Basic)

本主题描述 C# 和 Visual Basic 程序中最常用的特性。

  • 全局特性

  • 已过时的特性

  • 条件特性

  • Visual Basic 特性

全局特性

大多数特性适用于特定的语言元素,如类或方法;但是有些特性是全局的,它们适用于整个程序集或模块。 例如,AssemblyVersionAttribute 特性可用于向程序集中嵌入版本信息,如下例所示:

[assembly: AssemblyVersion("1.0.0.0")]
<Assembly: AssemblyVersion("1.0.0.0")>

全局特性在源代码中出现在任何顶级 using 指令(在 Visual Basic 中为 Imports)之后、任何类型、模块或命名空间声明之前。 全局特性可显示在多个源文件中,但这些文件必须在单一编译传递中编译。 对于 Visual Basic 项目,全局特性通常放在随 Visual Basic 项目自动创建的 AssemblyInfo.vb 文件中。 在 C# 项目中,它们放在 AssemblyInfo.cs 文件中。

程序集特性是提供程序集相关信息的值。 它们分成以下类别:

  • 程序集标识特性

  • 信息性特性

  • 程序集清单特性

  • 强名称特性

程序集标识特性

三个特性(如果适用,还有强名称)可确定程序集的标识:名称、版本和区域性。 这些特性构成程序集的完整名称,在代码中引用程序集时需要这些特性。 可以使用特性来设置程序集的版本和区域性。 但是,名称值由编译器、“程序集信息”对话框中的 Visual Studio IDE 或程序集链接器 (Al.exe) 在创建程序集时根据包含程序集清单的文件进行设置。 AssemblyFlagsAttribute 特性指定程序集的多份副本是否可以共存。

下表显示标识特性:

特性

用途

AssemblyName

详细描述程序集的标识。

AssemblyVersionAttribute

指定程序集的版本。

AssemblyCultureAttribute

指定程序集支持哪个区域性。

AssemblyFlagsAttribute

指定程序集是否支持在同一台计算机上、同一进程中或同一应用程序域中并行执行。

信息性特性

您可以使用信息性特性为程序集提供其他的公司或产品信息。 下表显示在 System.Reflection 命名空间中定义的信息性特性。

特性

用途

AssemblyProductAttribute

定义为程序集清单指定产品名称的自定义特性。

AssemblyTrademarkAttribute

定义为程序集清单指定商标的自定义特性。

AssemblyInformationalVersionAttribute

定义为程序集清单指定信息性版本的自定义特性。

AssemblyCompanyAttribute

定义为程序集清单指定公司名称的自定义特性。

AssemblyCopyrightAttribute

定义为程序集清单指定版权的自定义特性。

AssemblyFileVersionAttribute

指示编译器使用 Win32 文件版本资源的特定版本号。

CLSCompliantAttribute

指示程序集是否符合公共语言规范 (CLS)。

程序集清单特性

可以使用程序集清单特性提供程序集清单中的信息。 其中包括标题、说明、默认别名和配置。 下表显示在 System.Reflection 命名空间中定义的程序集清单特性。

特性

用途

AssemblyTitleAttribute

定义为程序集清单指定程序集标题的自定义特性。

AssemblyDescriptionAttribute

定义为程序集清单指定程序集说明的自定义特性。

AssemblyConfigurationAttribute

定义为程序集清单指定程序集配置(如发布或调试)的自定义特性。

AssemblyDefaultAliasAttribute

为程序集清单定义友好默认别名

强名称特性

在 Visual Studio 的早期版本中,使用强名称对程序集进行签名是使用以下程序集级特性执行的:

现在仍支持这样做,但是给程序集签名的首选方法是使用项目设计器中的**“签名页”**。 有关更多信息,请参见“项目设计器”->“签名”页如何:对程序集进行签名 (Visual Studio)

已过时的特性

Obsolete 特性将某个程序实体标记为一个建议不再使用的实体。 每次使用被标记为已过时的实体时,随后将生成警告或错误,这取决于特性是如何配置的。 例如:

    <System.Obsolete("use class B")> 
    Class A
        Sub Method()
        End Sub
    End Class

    Class B
        <System.Obsolete("use NewMethod", True)> 
        Sub OldMethod()
        End Sub

        Sub NewMethod()
        End Sub
    End Class

[System.Obsolete("use class B")]
class A
{
    public void Method() { }
}
class B
{
    [System.Obsolete("use NewMethod", true)]
    public void OldMethod() { }
    public void NewMethod() { }
}

在此例中,Obsolete 特性应用于类 A 和方法 B.OldMethod。 因为应用于 B.OldMethod 的特性构造函数的第二个参数设置为 true,所以此方法将导致编译器错误,而使用类 A 只会产生警告。 但是,调用 B.NewMethod 既不产生警告也不产生错误。

向特性构造函数提供的作为第一个参数的字符串将显示为警告或错误的一部分。 例如,当将它与前面的定义一起使用时,下面的代码将生成两个警告和一个错误:

' Generates 2 warnings:
' Dim a As New A
' Generate no errors or warnings:

Dim b As New B
b.NewMethod()

' Generates an error, terminating compilation:
' b.OldMethod()
// Generates 2 warnings:
// A a = new A();

// Generate no errors or warnings:
B b = new B();
b.NewMethod();

// Generates an error, terminating compilation:
// b.OldMethod();

为类 A 产生两个警告:一个用于声明类引用,一个用于类构造函数。

可在不使用参数的情况下使用 Obsolete 特性,但要包括此项已过时的原因及改用什么项的建议。

Obsolete 特性是一种单用途特性,并且可应用于允许特性的任何实体。 Obsolete 是 ObsoleteAttribute 的别名。

条件特性

Conditional 特性根据预处理标识符执行方法。 Conditional 特性是 ConditionalAttribute 的别名,可应用于方法或特性类。

在本示例中,Conditional 应用于方法以启用或禁用程序特定的诊断信息的显示:


#Const TRACE_ON = True
Imports System
Imports System.Diagnostics
Module TestConditionalAttribute
    Public Class Trace
        <Conditional("TRACE_ON")> 
        Public Shared Sub Msg(ByVal msg As String)
            Console.WriteLine(msg)
        End Sub

    End Class

    Sub Main()
        Trace.Msg("Now in Main...")
        Console.WriteLine("Done.")
    End Sub
End Module
#define TRACE_ON
using System;
using System.Diagnostics;

public class Trace
{
    [Conditional("TRACE_ON")]
    public static void Msg(string msg)
    {
        Console.WriteLine(msg);
    }
}

public class ProgramClass
{
    static void Main()
    {
        Trace.Msg("Now in Main...");
        Console.WriteLine("Done.");
    }
}

如果未定义 TRACE_ON 标识符,则将不会显示跟踪输出。

Conditional 特性经常与 DEBUG 标识符一起使用以启用调试版本的跟踪和日志记录功能(在发行版本中没有这两种功能),如下例所示:

<Conditional("DEBUG")> 
Shared Sub DebugMethod()

End Sub
[Conditional("DEBUG")]
static void DebugMethod()
{
}

当调用标记为条件的方法时,指定的预处理符号的存在或不存在决定是否包含或省略此调用。 如果定义了该符号,则包含调用;否则省略调用。 使用 Conditional 是将方法包括在 #if…#endif 块内的替代方法,它更整洁、更别致,也减少了出错的机会,如下例所示:

#If DEBUG Then
    Sub ConditionalMethod()
    End Sub
#End If
#if DEBUG
    void ConditionalMethod()
    {
    }
#endif

条件方法必须是类或结构声明中的方法,而且不能有返回值。

使用多个标识符

如果某个方法具有多个 Conditional 特性,且至少定义了其中一个条件符号(换言之,这些符号在逻辑上是使用 OR 运算符连接在一起的),则将包含对该方法的调用。 在本例中,A 或 B 的存在将导致方法调用:

<Conditional("A"), Conditional("B")> 
Shared Sub DoIfAorB()

End Sub
[Conditional("A"), Conditional("B")]
static void DoIfAorB()
{
    // ...
}

若要使用 AND 运算符获得在逻辑上链接符号的效果,可以定义序列条件方法。 例如,仅当 A 和 B 均已定义时,才能执行下面的第二种方法:

<Conditional("A")> 
Shared Sub DoIfA()
    DoIfAandB()
End Sub

<Conditional("B")> 
Shared Sub DoIfAandB()
    ' Code to execute when both A and B are defined...
End Sub
[Conditional("A")]
static void DoIfA()
{
    DoIfAandB();
}

[Conditional("B")]
static void DoIfAandB()
{
    // Code to execute when both A and B are defined...
}

使用具有特性类的条件

还可将 Conditional 特性应用于特性类定义。 在本例中,仅当定义了 DEBUG 时,自定义特性 Documentation 才向元数据添加信息。

<Conditional("DEBUG")> 
Public Class Documentation
    Inherits System.Attribute
    Private text As String
    Sub New(ByVal doc_text As String)
        text = doc_text
    End Sub
End Class

Class SampleClass
    ' This attribute will only be included if DEBUG is defined.
    <Documentation("This method displays an integer.")> 
    Shared Sub DoWork(ByVal i As Integer)
        System.Console.WriteLine(i)
    End Sub
End Class
[Conditional("DEBUG")]
public class Documentation : System.Attribute
{
    string text;

    public Documentation(string text)
    {
        this.text = text;
    }
}

class SampleClass
{
    // This attribute will only be included if DEBUG is defined.
    [Documentation("This method displays an integer.")]
    static void DoWork(int i)
    {
        System.Console.WriteLine(i.ToString());
    }
}

Visual Basic 特性

下表中列出了特定于 Visual Basic 的特性。

特性

用途

ComClassAttribute

指示编译器该类应该作为 COM 对象公开。

HideModuleNameAttribute

允许只使用模块需要的限定访问模块成员。

VBFixedStringAttribute

指定随文件输入和输出函数一起使用的结构中固定长度字符串的大小。

VBFixedArrayAttribute

指定随文件输入和输出函数一起使用的结构中固定数组的大小。

COMClassAttribute

使用 COMClassAttribute 可简化从 Visual Basic 创建 COM 组件的过程。 COM 对象与 .NET Framework 程序集差别很大,如果没有 COMClassAttribute,则从 Visual Basic 生成 COM 对象需要经过很多步骤。 对于标记为 COMClassAttribute 的类,编译器会自动执行这些步骤中的许多步骤。

HideModuleNameAttribute

使用 HideModuleNameAttribute 可以允许只使用模块需要的限定访问模块成员。

VBFixedStringAttribute

使用 VBFixedStringAttribute 可强制 Visual Basic 创建定长字符串。 字符串的长度在默认情况下是可变的,此特性在将字符串存储到文件时很有用。 以下代码对此进行了说明:

Structure Worker
    ' The runtime uses VBFixedString to determine 
    ' if the field should be written out as a fixed size.
    <VBFixedString(10)> Public LastName As String
    <VBFixedString(7)> Public Title As String
    <VBFixedString(2)> Public Rank As String
End Structure

VBFixedArrayAttribute

使用 VBFixedArrayAttribute 可声明固定大小的数组。 像 Visual Basic 字符串一样,数组的长度在默认情况下是可变的。 此特性在序列化数据或将数据写入文件时很有用。

请参见

参考

反射(C# 和 Visual Basic)

使用反射访问特性(C# 和 Visual Basic)

System.Reflection

Attribute

概念

C# 编程指南

利用特性扩展元数据

其他资源

Visual Basic 编程指南