F# int.MaxValue 是“不是一個有效的常量表達式”,但 System.Int32.MaxValue 是?
TL;DR: F# 編譯器
int在此上下文中解釋為intoperator,由 Eugene Fotin 確定並由Gene Belitski 擴展。最好的解決方法是使用System.Int32.MaxValue如下所述的唯一類型別名。考慮以下記錄類型:
type User = { Username : string }我想要
Username至少三個字元長,所以我使用StringLength屬性。沒有最大長度,所以我將其設置為int.MaxValue:type User = { [<StringLength(int.MaxValue, MinimumLength=3)>] Username : string }這給了我以下錯誤:
這不是有效的常量表達式或自定義屬性值。
如果我改用,一切都很美好
System.Int32:type User = { [<StringLength(System.Int32.MaxValue, MinimumLength=3)>] Username : string }如果我別名,它也會編譯
int:type User = { [<StringLength(num.MaxValue, MinimumLength=3)>] Username : string } and num = int或完全限定類型:
type User = { [<StringLength(Microsoft.FSharp.Core.int.MaxValue, MinimumLength=3)>] Username : string }我簽入了 F# 原始碼,並
int完全按照您的預期定義:type int32 = System.Int32 // Then, a few lines later… type int = int32這是怎麼回事?我假設 F# 原始類型在大多數情況下可以與其他類型互換,但看起來我的心智模型中缺少某些東西。
這就是 F# 類型推斷在不同上下文中工作的方式,其中不同的句法實體巧合地具有相同的名稱,在這種情況下
int可能是以下任何一種:
int:'T->int全名的作用Microsoft.FSharp.Core.Operators.inttype int = int32全名Microsoft.FSharp.Core.inttype int<'Measure> = int全名Microsoft.FSharp.Core.int<_>展示此工作的一種方法是以下場景:如果我們只是輸入
int;;在 FSI 我們會得到類似的東西
val it : (int -> int) = <fun:it@3>換句話說,它是一個不能有
MaxValue與之關聯的屬性的函式:> int.MaxValue;; int.MaxValue;; ----^^^^^^^^ ... error FS0039: The field, constructor or member 'MaxValue' is not defined這同樣適用於
int32,當在表達式上下文中使用時,FSI 將其推斷為另一個帶有簽名的函式(int -> int32)。現在說到
type num = int在這種情況下
int,推斷為 的類型名稱縮寫System.Int32,num類型縮寫也是如此,但現在名稱歧義沒有位置,因此num.MaxValue推斷出的正是我們所期望的,在 FSI 中給出> num.MaxValue;; val it : int = 2147483647最後,當您使用
Microsoft.FSharp.Core.int顯式引用類型實體時,沒有歧義的地方,因此它按預期工作。回到帶有屬性參數的案例 - 在這種情況下
int,類型推斷將其視為表達式的一部分以傳遞參數值,即作為函式,除非您明確或間接設置另一種解釋。