将方法类型参数限制为 class 泛型类型的基础

Constrain method type argument to be base of class generic type

我想确保方法类型参数是 class 泛型类型的基类型,所以首先我自然地写了这个:

public class FivePM<T> {
    public void drink<M>(M x) where T : M {}
}

有什么具体原因导致这不起作用吗?

背景

我写了容器 class Bag<B> 来存储不同实例之间共享的项目,所以如果将项目添加到另一个包中,它会自动从一个包中删除。这是由 BagSet<BT> 内部完成的,它存放普通物品的袋子。我希望 bag 通用类型成为集合中项目的最低常见类型,但不希望 constrian B 完全是 BT 但对于任何派生类型。 我已经设法使袋子的类型安全 public 接口满足我的要求,但由于通用约束限制,袋子构造看起来很笨拙,我不能使用列表初始化程序:

BagSet<object> bset = new BagSet<object>();
Bag<int> suitcase = bset.newBag<int>();

public class BagSet<T> : BagSetBase {
    public Bag<B> newBag<B>(string name = null, params B[] items) where B : T {
        var b = new Bag<B>(this, name);
        for (int i = 0; i < items.Length; i++) b.Add(items[i]);
        return b;
    }
}

总有一天会改进通用约束吗?也许我应该等一下再广泛地做这样的事情。

使用您的真实代码,如果您让 class Bag 采用两种类型并处理继承要求会怎么样 - 毕竟,您不关心 BagSet:

public class BagSet<T> {
    public Bag<B, T> newBag<B>(string name = null, params B[] items) where B : T {
        var b = new Bag<B, T>(this, name);
        for (int i = 0; i < items.Length; i++) b.Add(items[i]);
        return b;
    }
}

public class Bag<B, T> where B : T {
    BagSet<T> common;
    string bsname;

    public Bag(BagSet<T> bs, string name) {
        common = bs;
        bsname = name;
    }
    public void Add(B item) {
    }
}

然后你可以像这样声明它们:

var bset = new BagSet<object>();
var suitcase = bset.newBag<int>();

我想你也许可以让这个工作:

public class FivePM<T, M> where T : M 
{
    public void drink(M x) 
}

但是你的问题又让我困惑了,现在已经过了午夜,所以我可能错了,我可能误解了这个问题....或者也许不是?

Is there any specific reason why this can't work?

如果您的意思是有 合乎逻辑的 理由说明这种限制没有意义,那么没有。这是一个非常明智的约束,并且有支持这种约束的语言。 Java,例如。还有 Scala。

如果您的意思是这在 C# 中不起作用是有原因的,那很简单。 从来没有人在 C# 中实现过该功能。 为了使某个功能在 C# 中工作,必须有人想到它、设计它、编写规范、实施规范、编写测试,然后将其运送给客户。在那些必要的步骤中,只有第一步发生了。

Are generic constrains going to be improved someday?

要求预测未来的问题在 Stack Overflow 上属于题外话。我们没有能力可靠地预测未来。

如果您希望此功能出现在 C# 的未来版本中,请考虑在 github 论坛上提倡它。