Jor*_*ray 10 .net f# data-annotations
TL; DR: F#编译器解释int在这种情况下为int操作者,如由Eugene Fotin确定和通过基因Belitski时膨胀.最佳解决方法是使用System.Int32.MaxValue或如下所述的唯一类型别名.
请考虑以下记录类型:
type User = {
Username : string
}
Run Code Online (Sandbox Code Playgroud)
我想要Username至少三个字符,所以我使用该StringLength属性.没有最大长度,所以我将它设置为int.MaxValue:
type User = {
[<StringLength(int.MaxValue, MinimumLength=3)>]
Username : string
}
Run Code Online (Sandbox Code Playgroud)
这给了我以下错误:
这不是有效的常量表达式或自定义属性值.
如果我使用的话,一切都是桃子的System.Int32:
type User = {
[<StringLength(System.Int32.MaxValue, MinimumLength=3)>]
Username : string
}
Run Code Online (Sandbox Code Playgroud)
如果我别名它也会编译int:
type User = {
[<StringLength(num.MaxValue, MinimumLength=3)>]
Username : string
}
and num = int
Run Code Online (Sandbox Code Playgroud)
或完全符合类型:
type User = {
[<StringLength(Microsoft.FSharp.Core.int.MaxValue, MinimumLength=3)>]
Username : string
}
Run Code Online (Sandbox Code Playgroud)
我检查了F#源代码,并且int完全按照您的预期定义:
type int32 = System.Int32
// Then, a few lines later…
type int = int32
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?我假设F#原始类型在大多数情况下都可与其他类型互换,但看起来我的心理模型中缺少某些东西.
Gen*_*ski 11
这就是F#类型推断如何在不同的语境中工作,其中不同的语法实体巧合地具有相同的名称,在以下情况中int可以是以下任何一种:
int:'T->int全名功能Microsoft.FSharp.Core.Operators.inttype int = int32 全名 Microsoft.FSharp.Core.inttype int<'Measure> = int 全名 Microsoft.FSharp.Core.int<_>演示此工作的一种方法是以下场景:如果我们只是输入
int;;
Run Code Online (Sandbox Code Playgroud)
在FSI,我们会得到类似的东西
val it : (int -> int) = <fun:it@3>
Run Code Online (Sandbox Code Playgroud)
换句话说,它是一个不能具有MaxValue与之关联的属性的函数:
> int.MaxValue;;
int.MaxValue;;
----^^^^^^^^
... error FS0039: The field, constructor or member 'MaxValue' is not defined
Run Code Online (Sandbox Code Playgroud)
同样适用于int32,当在表达的上下文中使用时,由FSI推断为具有签名的另一个函数(int -> int32).
现在说到了
type num = int
Run Code Online (Sandbox Code Playgroud)
在这个上下文中int被推断为类型名称的缩写System.Int32,因此num也是类型缩写,但现在名称歧义没有位置,因此num.MaxValue推断出我们期望它的确切含义,在FSI中给出
> num.MaxValue;;
val it : int = 2147483647
Run Code Online (Sandbox Code Playgroud)
最后,当您使用Microsoft.FSharp.Core.int显式引用类型实体时,没有模糊性的地方,因此它按预期工作.
回到带有属性参数的用例 - 在此上下文int中,类型推断将其作为表达式的一部分来处理,以传递参数值,即作为函数,除非您明确或间接设置另一个解释.