我创建了一个F#类来表示一个数组,该数组为特定枚举的每个值分配一个元素。我正在使用一个显式构造函数,它创建一个从枚举值到数组索引的字典,以及一个Item属性,以便您可以编写如下表达式:
let my_array = new EnumArray<EnumType, int>
my_array.[EnumType.enum_value] <- 5
但是,我在下面标有'// FS0670'的行上遇到以下模糊的编译错误。
error FS0670: This code is not sufficiently generic.
The type variable ^e when ^e : enum<int> and ^e : equality
and ^e : (static member op_Explicit : ^e -> int)
could not be generalized because it would escape its scope.
我很茫然 - 任何人都可以解释这个错误吗?
type EnumArray< 'e, 'v when 'e : enum<int> //'
and 'e : equality
and 'e : (static member op_Explicit : 'e -> int) > =
val enum_to_int : Dictionary<'e, int> //'
val a : 'v array //'
new() as this =
{
enum_to_int = new Dictionary<'e, int>() //'
a = Array.zeroCreate (Enum.GetValues(typeof<'e>).Length) //'
}
then
for (e : obj) in Enum.GetValues(typeof<'e>) do //'
this.enum_to_int.Add(e :?> 'e, int(e :?> 'e))
member this.Item
with get (idx : 'e) : 'v = this.a.[this.enum_to_int.[idx]] // FS0670
and set (idx : 'e) (c : 'v) = this.a.[this.enum_to_int.[idx]] <- c
答案 0 :(得分:5)
你走了:
open System
open System.Collections.Generic
type EnumArray<'e, 'v when 'e : enum<int> and 'e : equality>() =
let dict = new Dictionary<'e, int>() //'
let values = Enum.GetValues(typeof<'e>) //'
let a = Array.zeroCreate values.Length
do
for (o : obj) in values do
let e = o :?> 'e //'
dict.Add(e, LanguagePrimitives.EnumToValue(e))
member this.Item
with get idx = a.[dict.[idx]]
and set idx c = a.[dict.[idx]] <- c
let d = new EnumArray<StringSplitOptions, string>()
d.[StringSplitOptions.None] <- "foo"
d.[StringSplitOptions.RemoveEmptyEntries] <- "bar"
一个关键方面是LanguagePrimitives.EnumToValue,它消除了对静态成员约束的需要。 (使用静态成员约束已经够糟糕了,但是当它们失败时,编译器诊断会更糟糕。)