阅读所有建议的相关问题后,我找不到我的问题的答案。给您写信,希望您能尽快回答,并宽容地判断我在这方面的知识不足。
我有一个类型来体现一个函数定义:

type FunctionDefinition<'a>(exec:int->(Data.Reader->'a)) =
    member x.Exec = exec
    member x.ReturnType = typeof<'a>
如您在此处看到的,exec应该是一个接受一个int参数的函数,并返回另一个接受一个Data.Reader参数并返回'a类型的值的函数(例如一个枯燥的短语!)。 Data.Reader的定义在这里无关紧要。
另外,我有一个字典来保留string->FunctionDefinition对,如下所示:
let FUNCTIONS = new Generic.Dictionary<string, FunctionDefinition<obj>>()
FunctionDefinition中的FUNCTIONS实例将拥有几种类型的函数,这就是为什么它是FunctionDefinition<obj>的原因(我相信这是邪恶的根源,但我无法避免,因此我在这里)。
然后,我将一些函数包装在FunctionDefinition中并放入FUNCTIONS中:
/// Function definitions
let unchanged (id:int) =
    let mutable last = null
    fun (reader:Data.Reader) ->
        if last = null then
            false
        else
            let cur = reader.GetValue(id)
            let ret = last.Equals(cur)
            last <- cur
            ret

let changed (id:int) =
    let un = unchanged id
    fun(reader:Data.Reader) ->
        not (un reader)

let dummyfortesting (id:int) =
    fun(x) -> "yam-yam"
我以为我可以将这些功能添加到我的字典中,但是……没什么!如下代码:
FUNCTIONS.Add("unchanged", new FunctionDefinition<bool>(unchanged))
                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FUNCTIONS.Add("changed", new FunctionDefinition<bool>(changed))
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FUNCTIONS.Add("dummy", new FunctionDefinition<string>(dummyfortesting))
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
给出明确的错误消息:
// The type 'obj' does not match the type 'bool'
// The type 'obj' does not match the type 'bool'
// The type 'obj' does not match the type 'string'
而以下是正确的:
typeof<bool>.isSubclassOf(typeof<obj>) // -> true
这是不公平的,不是吗?

问题是
如何实例化FUNCTIONS字典以容纳几个FunctionDefinition<bool>FunctionDefinition<string>实例?
还是除了为返回不同类型的函数保留通用FunctionDefinition类型之外,还有其他解决方案吗?

一种解决方案是将所需的类型作为参数传递给FunctionDefinition的构造函数,如下所示:
type FunctionDefinition(typ:System.Type, exec:int->(Data.Reader->???)) =
    member x.Exec = exec
    member x.ReturnType = typ
但是这里不清楚如何声明exec
我希望我足够清楚。
非常感谢。
您忠诚的,
h

最佳答案

您正在创建的字典需要保存相同类型的值。如果使用不同的类型参数创建两个FunctionDefinition<'T>值,则它们将是不同的类型,因此无法将它们组合在一个字典中。

解决此的一种方法是定义一个非通用接口(interface),并创建一个存储该接口(interface)值的字典(将由所有通用FunctionDefinition<'T>对象实现)

type IFunctionDefinition =
  abstract ReturnType : System.Type
  abstract Exec : int -> (Reader -> obj)

let dict = new Dictionary<string, IFunctionDefinition>()
Exec函数必须返回obj,因为在将函数存储在(同质)字典中之后无法恢复类型信息。然后,您的具体类型可以实现接口(interface):
type FunctionDefinition<'a>(exec:int->(Reader->'a)) =
  member x.Exec = exec
  interface IFunctionDefinition with
    member x.ReturnType = typeof<'a>
    member x.Exec n = fun rdr -> box (exec n rdr)

现在,您可以将创建的函数定义添加到字典中,因为它们实现了 public 接口(interface):
let foo = FunctionDefinition<int>(fun _ _ -> 42)
dict.Add("foo", foo)

另一种方法将是使类型定义为非泛型的。使用字典中的函数确定它们返回的值时,需要进行一些动态类型测试。您可以通过使用已区分的联合作为返回类型来使其明确:
type ResultType =
  | String of string
  | Bool of bool
  // etc. for all supported return types

09-25 21:36