特性 (F#)

属性使元数据能够应用于编程构造。

语法

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

言论

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

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

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

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: AssemblyVersion("1.0.0.0")>]
name
[<``module``: MyCustomAttributeThatWorksOnModules>]
方法
[<MyCustomAttributeThatWorksOnMethods>]
let someFunction() = 42
class
[<MyCustomAttributeThatWorksOnClasses>]
type MyClass(myValue: int) =
    member _.MyValue = myValue
struct
[<MyCustomAttributeThatWorksOnStructs>]
[<Struct>]
type MyStruct(myValue: int) =
    member _.MyValue = myValue
接口
[<MyCustomAttributeThatWorksOnInterfaces>]
type MyInterface =
    abstract member Prop: string
枚举
[<MyCustomAttributeThatWorksOnEnums>]
type Color =
    | Red = 0
    | Green = 1
    | Blue = 2
构造函数
type MyClass(myValue: int) =
    member _.MyValue = myValue

    [<MyCustomAttributeThatWorksOnCtors>]
    new () = MyClass 42
return
let function1 x : [<return: MyCustomAttributeThatWorksOnReturns>] int = x + 1
field
[<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

另请参阅