特性 (F#)

通过特性可将元数据应用于编程构造。

语法

[<target:attribute-name(arguments)>]

备注

在以前的语法中,target 是可选的,如果存在,则指定应用特性的程序实体类型。 target 的有效值显示在本文档稍后显示的表中。

attribute-name 是指有效特性类型的名称(可能用名称空间限定),可带有或不带有通常在特性类型名称中使用的后缀 Attribute。 例如,在此上下文中,ObsoleteAttribute 类型可简写为 Obsolete

arguments 是指特性类型的构造函数的参数。 如果特性具有无参数构造函数,就可省略参数列表和括号。 特性支持位置参数和命名参数。 位置参数是按其显示顺序使用的参数。 如果特性具有公共属性,就可以使用命名参数。 可通过在参数列表中使用以下语法来设置它们。

property-name = property-value

此类属性初始化可采用任意顺序,但它们必须跟在位置参数之后。 下面是使用位置参数和属性初始化的特性示例:

open System.Runtime.InteropServices

[<DllImport("kernel32", SetLastError=true)>]
extern bool CloseHandle(nativeint handle)

在本例中,特性是 DllImportAttribute,这里以缩写形式使用。 第一个实参是位置参数,第二个是属性。

特性是一种 .NET 编程构造,它使称为特性的对象能够与类型或其他程序元素关联。 应用特性的程序元素称为特性目标。 特性通常包含其目标的相关元数据。 在此上下文中,元数据可以是除字段和成员外有关类型的任何数据。

F# 中的特性可应用于以下编程构造:函数、方法、程序集、模块、类型(类、记录、结构、接口、委托、枚举、联合等)、构造函数、属性、字段、参数、类型参数和返回值。 不允许在类、表达式或工作流表达式的 let 绑定中使用特性。

通常,特性声明直接显示在特性目标的声明之前。 可以一起使用多个特性声明,如下所示:

[<Owner("Jason Carlson")>]
[<Company("Microsoft")>]
type SomeType1 =

可以使用 .NET 反射在运行时查询特性。

可以单独声明多个特性,如前面的代码示例所示,如果使用分号分隔各个特性和构造函数,也可在一组括号中声明这些特性,如下所示:

[<Owner("Darren Parker"); Company("Microsoft")>]
type SomeType2 =

通常遇到的特性包括 Obsolete 特性、与安全注意事项有关的特性、与 COM 支持有关的特性、与代码所有权有关的特性,以及指示类型是否可以序列化的特性。 以下示例演示 Obsolete 特性的用法。

open System

[<Obsolete("Do not use. Use newFunction instead.")>]
let obsoleteFunction x y =
  x + y

let newFunction x y =
  x + 2 * y

// The use of the obsolete function produces a warning.
let result1 = obsoleteFunction 10 100
let result2 = newFunction 10 100

对于特性目标 assemblymodule,你可将这些特性应用到程序集中的顶级 do 绑定。 可以在特性声明中包含单词 assembly``module``,如下所示:

open System.Reflection
[<assembly:AssemblyVersionAttribute("1.0.0.0")>]
[<``module``:MyCustomModuleAttribute>]
do
   printfn "Executing..."

如果省略应用于 do 绑定的特性的特性目标,F# 编译器将尝试确定对该特性有意义的特性目标。 许多特性类具有 System.AttributeUsageAttribute 类型的特性,该类型包含该特性支持的可能目标的相关信息。 如果 System.AttributeUsageAttribute 指示特性支持将函数用作目标,则将特性应用于程序的主入口点。 如果 System.AttributeUsageAttribute 指示特性支持将程序集用作目标,则编译器将特性应用于程序集。 大多数特性并不同时应用于函数和程序集,但如果遇到同时应用的情况,则将特性应用于程序的主函数。 如果显式指定了特性目标,则该特性将应用于指定目标。

虽然通常不需要显式指定特性目标,但下表显示了目标在特性中的有效值以及用法示例:

特性目标 示例
程序集 (assembly)
[<assembly: AssemblyVersion("1.0.0.0")>]
name
[<``module``: MyCustomAttributeThatWorksOnModules>]
return
let function1 x : [<return: MyCustomAttributeThatWorksOnReturns>] int = x + 1
字段
[<DefaultValue>] val mutable x: int
property
[<Obsolete>] this.MyProperty = x
param
member this.MyMethod([<Out>] x : ref<int>) = x := 10
type
[<type: StructLayout(LayoutKind.Sequential)>]
type MyStruct =
  struct
    val x : byte
    val y : int
  end

另请参阅