给定以下c#中的CRTP类型:
public abstract class DataProviderBase<TProvider>
where TProvider : DataProviderBase<TProvider> { }
如何在f#中获得它的泛型类型定义?
let typeDef = typedefof<DataProviderBase<_>>
产生错误:
对类型推断变量应用默认类型'DataProviderBase<'a>'时,类型约束不匹配。当统一" a "one_answers" DataProviderBase<'a> "时,结果类型将是无限的,请考虑添加进一步的类型约束
在c#中应该是:
var typeDef = typeof(DataProviderBase<>);
更新我找到了一个解决方法:
[<AbstractClass>]
type DummyProvider() =
inherit DataProviderBase<DummyProvider>()
let typeDef = typeof<DummyProvider>.BaseType.GetGenericTypeDefinition()
有没有另一种不需要额外类型的方法?
我认为这实际上是一个非常好的问题。我没有找到更好的解决方法。您可以像这样使用typedefof
来稍微简化您的工作:
let typeDef = typedefof<DataProviderBase<DummyProvider>>
技术细节
问题在于f#的typedefof<'T>
只是一个接受类型参数的普通函数(不像c#中的typeof
,它是一个操作符)。为了调用它,您需要给它一个实际的类型,然后函数将在掩护下调用GetGenericTypeDefinition
。
typedefof<option<_>>
工作的原因是f#指定了一个默认类型作为参数(在本例中为obj
)。一般来说,f#选择匹配约束的不太具体的类型。在你的例子中:
DataProviderBase<_>
将变成DataProviderBase<DataProviderBase<_>>
,依此类推。
除非您定义一个新类型(就像在您的变通方法中一样),否则没有具体类型可以用作typedefof<...>
的类型参数。在这种情况下,默认机制根本不起作用…