F#泛型和铸造

时间:2011-04-06 13:42:13

标签: generics f# casting

在阅读了所有相关的问题之后,我找不到我的问题的答案。写信给你,希望你很快就会回答,并且会在这个领域轻率地判断我缺乏知识。

我有一个体现函数定义的类型:

type FunctionDefinition<'a>(exec:int->(Data.Reader->'a)) =
    member x.Exec = exec
    member x.ReturnType = typeof<'a>

正如您在此处所看到的,exec应该是一个函数,它接受一个int参数并返回另一个函数,该函数接受一个Data.Reader参数并返回类型{{ 1}}(这样一个令人筋疲力尽的短语!)。 '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 字典以容纳多个FUNCTIONSFunctionDefinition<bool>个实例?

或者除了为返回不同类型的函数保留通用FunctionDefinition<string>类型之外,还有其他解决方案吗?


一种解决方案是将所需类型作为参数传递给FunctionDefinition的构造函数,如下所示:

FunctionDefinition

但目前尚不清楚如何声明type FunctionDefinition(typ:System.Type, exec:int->(Data.Reader->???)) = member x.Exec = exec member x.ReturnType = typ

我希望我足够清楚。

非常感谢你。

真诚的,

的Kh

1 个答案:

答案 0 :(得分:5)

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

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

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

let dict = new Dictionary<string, IFunctionDefinition>()

Exec函数必须返回obj,因为在(同类)字典中存储函数后无法恢复类型信息。然后,您的具体类型可以实现接口:

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)

现在您可以将创建的函数定义添加到字典中,因为它们实现了公共接口:

let foo = FunctionDefinition<int>(fun _ _ -> 42)
dict.Add("foo", foo)

另一种方法是使类型定义非泛型。在使用字典中的函数来确定它们返回的值时,您需要进行一些动态类型测试。您可以通过使用区分联合作为返回类型来使其显式:

type ResultType =
  | String of string
  | Bool of bool
  // etc. for all supported return types
相关问题