问题描述
在C#中提供以下 CRTP 类型:
Given the following CRTP type in C#:
public abstract class DataProviderBase<TProvider>
where TProvider : DataProviderBase<TProvider> { }
如何在F#中获取其通用类型定义?
How would I get its generic type definition in F#?
let typeDef = typedefof<DataProviderBase<_>>
产生错误:
在C#中,它将是:
var typeDef = typeof(DataProviderBase<>);
更新
我找到了一种解决方法:
UPDATE
I found a workaround:
[<AbstractClass>]
type DummyProvider() =
inherit DataProviderBase<DummyProvider>()
let typeDef = typeof<DummyProvider>.BaseType.GetGenericTypeDefinition()
还有没有其他类型的方法吗?
Is there another way to do it, without the extra type?
推荐答案
我认为这实际上是一个很好的问题.我没有找到更好的解决方法.您可以像这样使用typedefof
来稍微简化您的解决方法:
I think this is actually a very good question. I didn't find a better workaround for this.You can slightly simplify your workaround by using typedefof
like this:
let typeDef = typedefof<DataProviderBase<DummyProvider>>
技术细节
问题在于F#的typedefof<'T>
只是一个接受类型参数的普通函数(与C#中的typeof
不同,后者是一个运算符).为了调用它,您需要给它一个实际的类型,然后该函数将在幕后调用GetGenericTypeDefinition
.
The problem is that F#'s typedefof<'T>
is just an ordinary function that takes a type argument (unlike typeof
in C#, which is an operator). In order to call it, you need to give it an actual type and the function will then call GetGenericTypeDefinition
under the cover.
typedefof<option<_>>
起作用的原因是F#指定了 default 类型作为参数(在本例中为obj
).通常,F#选择与约束匹配的不太具体的类型.对于您的情况:
The reason why typedefof<option<_>>
works is that F# specifies a default type as an argument (in this case obj
). In general, F# chooses the less concrete type that matches the constraints. In your case:
DataProviderBase<_>
将变为DataProviderBase<DataProviderBase<_>>
,依此类推.
除非您定义新类型(如在解决方法中那样),否则没有任何具体类型可用作typedefof<...>
的类型参数.在这种情况下,默认机制根本不起作用...
Unless you define a new type (as in your workaround), there is no concrete type that could be used as a type argument of typedefof<...>
. In this case, the defaulting mechanism simply doesn't work...
这篇关于如何获取CRTP类型的通用类型定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!