简体   繁体   中英

Use generic base class in a collection of classes derived from generic

I'm coming to C# from Java and I was unable to find out how to resolve the following issue:

I have a generic base class:

class MyBase<T>  where T : SomeAncestorOfTs
{ ... }

and then a few specialized classes ( A , B , C ...) derived from it, like:

class A : MyBase<SomeSpecificT> 
{ ... }

Now somewhere in my code I would like to create a Dictionary of various descendants of MyBase : something like Dictionary<string,MyBase<>> , but that's not working.

Is there a way in C# other than doing Dictionary<String,Object> ?

In Java this would be easily achieved by doing HashMap<String,MyBase<? extends SomeAncestorOfTs>> HashMap<String,MyBase<? extends SomeAncestorOfTs>> .

UPDATE : T is supposed to have a common base class ( SomeAncestorOfT ).

It cannot be done like that directly. My suggestion would be to add yet another, non-generic, base class:

class MyBase
{ ... }

class MyBase<T> : MyBase
{ ... }

And then make a dictionary of that base: Dictionary<string,MyBase>

How about something like this:

public class SuperBase
{
}

internal class MyBase<T> : SuperBase
{
}


internal class A : MyBase<string>
{
    public void DoStuff()
    {
        Dictionary<string, SuperBase> _dict = new Dictionary<string, SuperBase>();

        _dict.Add("first", new MyBase<int>());
        _dict.Add("second", new MyBase<object>());
        _dict.Add("third", new MyBase<string>());
    }
}

This does not give a compilation error as it stands at least (although I can't guarantee that it won't produce other unforeseen headaches down the road).

The short answer is no you cannot do this in C#. MyBase<int> and MyBase<string> do not share a base class other than object . Personally, I don't see what I would do with it even if it worked syntactically.

If all those instances share a behavior, let them all implement that interface and have a dictionary of those.

This seems to work fine, does it help you?

class Program
{
    static void Main(string[] args)
    {
        Dictionary<string, MyBase> dic = new Dictionary<string, MyBase>();
        A<int> test= new A<int>();

        dic.Add("test", test);
    }
}
class MyBase
{ }
class A<T> : MyBase
{}
class MyBase<T>
{ ... }

class A : MyBase<SomeSpecificT> 
{ ... }

if you don't want to use Object, you can use dynamic.

var dict = new Dictionary<String, MyBase<dynamic>>();

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