【问题标题】:How to get generic type definition for CRTP type如何获取 CRTP 类型的泛型类型定义
【发布时间】:2011-07-21 21:52:18
【问题描述】:

给定以下CRTP,在 C# 中输入:

public abstract class DataProviderBase<TProvider>
    where TProvider : DataProviderBase<TProvider> { }

如何在 F# 中获得其泛型类型定义?

let typeDef = typedefof<DataProviderBase<_>>

产生错误:

为类型推断变量应用默认类型“DataProviderBase”时类型约束不匹配。统一 ''a' 和 'DataProviderBase' 时生成的类型将是无限的 考虑添加更多类型约束

在 C# 中,它是:

var typeDef = typeof(DataProviderBase<>);

更新

我找到了解决方法:

[<AbstractClass>]
type DummyProvider() =
  inherit DataProviderBase<DummyProvider>()

let typeDef = typeof<DummyProvider>.BaseType.GetGenericTypeDefinition()

没有额外的类型,还有其他方法吗?

【问题讨论】:

    标签: reflection f# crtp


    【解决方案1】:

    我认为这实际上是一个非常好的问题。我没有找到更好的解决方法。 您可以像这样使用typedefof 稍微简化您的解决方法:

    let typeDef = typedefof<DataProviderBase<DummyProvider>>
    

    技术细节

    问题在于 F# 的 typedefof&lt;'T&gt; 只是一个接受类型参数的普通函数(与 C# 中的 typeof 不同,它是一个运算符)。为了调用它,你需要给它一个实际的类型,然后函数会在后台调用GetGenericTypeDefinition

    typedefof&lt;option&lt;_&gt;&gt; 起作用的原因是 F# 将 default 类型指定为参数(在本例中为 obj)。通常,F# 选择与约束匹配的不太具体的类型。在你的情况下:

    DataProviderBase&lt;_&gt; 将变为 DataProviderBase&lt;DataProviderBase&lt;_&gt;&gt; 等等。

    除非您定义一个新类型(如您的解决方法),否则没有具体类型可以用作typedefof&lt;...&gt; 的类型参数。在这种情况下,默认机制根本不起作用......

    【讨论】:

    • 知道为什么 F# 团队选择将 typeof/typedefof 实现为函数吗?我喜欢你对解决方法的简化。
    • @Daniel - 我没有权威的答案,但我猜他们这样做是因为他们可以。 typeof 函数使用一些内联 IL,另一个非常简单:github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/…。它几乎像 C# 的运算符一样工作(你的例子是我知道的第一个失败的例子),但不需要新的语法。
    • @Tomas, @Daniel - 其他约束也可能有问题:考虑 type T&lt;'a when 'a : enum&lt;int&gt;&gt;() = class end,它也有同样的问题。
    • @kvb:有鉴于此,它似乎有点坏了。是否应该作为错误提交?
    • @Daniel - 几年前我发送了一份错误报告......我会重新提出这个问题。
    猜你喜欢
    • 1970-01-01
    • 2019-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    相关资源
    最近更新 更多