将方法类型参数作为类泛型类型的基础

时间:2018-01-30 21:38:37

标签: c# generics type-constraints

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

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

是否有任何具体原因可以解决这个问题?

背景

我编写了容器类Bag<B>,它存储了在不同实例之间共享的项目,因此如果项目被添加到另一个包中,则会自动从一个包中删除该项目。这是由BagSet<BT>内部完成的,其中包含普通物品袋。我希望bag generic类型成为集合中最低级别的常用类型,但并不希望constrian B完全BT,而是任何派生类型。 我设法为包满足我的要求制作了类型安全的公共界面,但由于通用约束限制,包结构看起来很尴尬,我不能使用列表初始化器:

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;
    }
}

通用约束有一天会得到改善吗?也许我应该等到广泛地做这些事情之前。

3 个答案:

答案 0 :(得分:1)

使用您的真实代码,如果您使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>();

答案 1 :(得分:1)

  

是否有任何具体原因可以解决这个问题?

如果你的意思是存在逻辑的原因,为什么这种约束没有意义,那么没有。这是一个非常明智的约束,有些语言支持这种约束。例如,Java。斯卡拉。

如果你的意思是为什么这在C#中没有工作,这很容易。 没有人在C#中实现过该功能。为了使功能在C#中运行,有人必须考虑它,设计它,编写规范,实现规范,编写测试,然后发货它给客户。在这些必要步骤中,只发生了第一个步骤。

  

有一天通用约束会有所改善吗?

要求预测未来的问题在Stack Overflow上是偏离主题的。我们没有能力可靠地预测未来。

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

答案 2 :(得分:0)

我认为你可能能够实现这个目标:

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

但是你的问题再次让我感到困惑,这已经过了午夜,所以我可能错了,我可能会误解这个问题......或者可能不是?