简体   繁体   中英

Constrain method type argument to be base of class generic type

I would like to ensure that method type argument is base type of class generic type so first I naturally wrote this:

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

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

Background

I wrote container class Bag<B> which stores items shared between different instances, so an item is automatically removed from one bag if it's added to another. This is done internaly by the BagSet<BT> which hold bags for common items. I wanted for bag generic type to be the lowest common type of items in sets but don't want constrian B to be exactly BT but to any derived type. I've managed to make type safe public interface for the bag fulfill my requirements but because of generic constrains limitations, bags construction looks awkward and I can't use list initializer:

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

Are generic constrains going to be improved someday? Maybe I should wait before making such things extensively.

Using your real code, what if you made class Bag take two types and handle the inheritance requirement - after all, you don't care about that in a 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) {
    }
}

Then you can declare them like so:

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

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

If you mean is there a logical reason why that kind of constraint doesn't make sense, then no. That's a perfectly sensible constraint, and there are languages that support that sort of constraint. Java, for instance. And Scala.

If you mean is there a reason why this doesn't work in C# , that's easy. No one ever implemented that feature in C#. In order for a feature to work in C#, someone has to think of it, design it, write a specification, implement the specification, write tests, and then ship it to customers. Of those necessary steps, only the first one happened.

Are generic constrains going to be improved someday?

Questions asking for a prediction of the future are off-topic on Stack Overflow. We have no ability to reliably predict the future.

If you'd like this feature to be in a future version of C#, consider advocating for it on the github forum.

I think you might be able to get this working:

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

But then again your question confused me and it is past midnight here so I might be wrong and I might misunderstood the question.... Or maybe not?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM