【问题标题】:Generic class type constraint with a generic class having another constraint泛型类类型约束,泛型类具有另一个约束
【发布时间】:2021-04-21 16:30:31
【问题描述】:

假设我有一个通用类

public class G<T> {
}

我想将 final 类声明为

public class F<T> where T : G<T> {
}

这似乎是可能的,但是如果我想使任务复杂化并像这样向 G 类添加一个约束

public class A {
}

public class DA : A {
}

public class DB : A {
}

public class G<T> where T : A {
}

最后我想这样做

public class F<T> where T : G<T> {
}

这不起作用,它说 T 必须是 A 类型,这是可以理解的,看起来我可以像这样重写它

public class F<T, U> where T : G<U> where U : A {
}

但在这种情况下,用法有一个多余的声明

public class DF : F<G<DA>, DA> {
}

在使用类 F 时我必须重复 DA 两次,即使很清楚如果我使用 G 作为泛型类型,G 的泛型类型是 DA。有没有办法避免这种冗余?

【问题讨论】:

    标签: c# generics generic-constraints


    【解决方案1】:

    最后我想这样做

    public class F<T> where T : G<T> {
    }
    

    但这似乎没有多大意义。您希望FT 参数化,这必须是G&lt;X&gt;,其中X 又是T,即G&lt;X&gt;,其中X 又是T,依此类推...是递归定义。

    我认为您真正想要定义的是(所有示例都是无效的 C#)

    public class F<T1<T2>> where T1 : G<T2> where T2 : A {
    }
    

    或许

    public class F<T1> where T1 : G<T2> where T2 : A {
    }
    

    或许

    public class F<G<T>> where T : A {
    }
    

    那些“泛型的泛型”被称为高级类型,但不幸的是,C# 不支持它们。例如,Haskell 可以,其他一些函数式语言也可以。

    有一个模仿 HKT 的 C# library,它使用您找到的解决方法:指定内部类型两次。

    【讨论】:

    • 您不能声明class F&lt;G&lt;T&gt;&gt;,但您当然可以实例化嵌套的泛型类型。 Dictionary&lt;int, List&lt;List&lt;int&gt;&gt;&gt; foo 是一个完全有效的类型。
    • @PMF Higher-kinded types 与嵌套泛型非常不同。
    • @PMF 以你的例子为例,更高种类的类型将类似于Dictionary&lt;int, T&lt;int&gt;,其中T 预计不仅是List,而且是任何一种等级为 1 和可参数化为int
    • 我已经理解它的含义,尽管我并没有真正看到它的用途。是的,我不能将泛型声明为Dictionary&lt;int, T&lt;int&gt;&gt;,但我仍然可以声明可以由此类生成的所有具体类型。
    • 一个示例用法是扩展函数To(),它将IEnumerable&lt;T&gt; 转换为任何TCollection&lt;T&gt;List&lt;int&gt; l = new[] { 1 }.To&lt;List&lt;int&gt;&gt;()。不是很壮观,但这只是 HKT 可以做的事情的皮毛。
    猜你喜欢
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    相关资源
    最近更新 更多