如何获取 CRTP 类型的通用类型定义

发布于 2024-11-26 05:13:25 字数 901 浏览 3 评论 0 原文

给定 C# 中的以下 CRTP 类型:

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

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

let typeDef = typedefof<DataProviderBase<_>>

产生错误:

应用默认类型“DataProviderBase<'a>”时类型约束不匹配对于类型推断变量。当统一 ''a' 和 'DataProviderBase<'a>' 时,结果类型将是无限的考虑添加更多类型约束

在 C# 中,这将是:

var typeDef = typeof(DataProviderBase<>);

更新

我找到了一个解决方法:

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

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

是否有另一种方法可以做到这一点,而不需要额外的类型?

Given the following CRTP type in C#:

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

How would I get its generic type definition in F#?

let typeDef = typedefof<DataProviderBase<_>>

yields the error:

Type constraint mismatch when applying the default type 'DataProviderBase<'a>' for a type inference variable. The resulting type would be infinite when unifying ''a' and 'DataProviderBase<'a>' Consider adding further type constraints

In C#, it would be:

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毁梦 2024-12-03 05:13:25

我觉得这其实是一个非常好的问题。我没有找到更好的解决方法。
您可以使用 typedefof 稍微简化您的解决方法,如下所示:

let typeDef = typedefof<DataProviderBase<DummyProvider>>

技术细节

问题在于 F# 的 typedefof<'T> 只是一个普通函数它接受一个类型参数(与 C# 中的 typeof 不同,它是一个运算符)。为了调用它,您需要给它一个实际类型,然后该函数将在幕后调用 GetGenericTypeDefinition

typedefof> 起作用的原因是 F# 指定一个默认类型作为参数(在本例中是 obj)。一般来说,F# 选择与约束匹配的不太具体的类型。在您的情况下:

DataProviderBase<_> 将变为 DataProviderBase> 等等。

除非您定义新类型(如解决方法中所示),否则没有具体类型可以用作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>>

TECHNICAL DETAILS

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.

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<_> will become DataProviderBase<DataProviderBase<_>> and so on.

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文