1

How can I create a generic with two parameter where the second parameter is dependent on the first. In this case I'm creating a hash class, where I need both the type of the object and the key that identifies it.

Some simplified code for explanation:

class MyCache<T,Key> : where T is CommonImpl {
   Dictionary<Key,T> cache;

   T Get( Key v ) {
      ...
      var newValue = new T(v);
      return newValue;
   }
}

class ImplA : CommonImpl {
   public ImplA( String key ) { }
}

class ImplB : CommonImpl {
   public ImplB( SomeType key ) { }
}

Where I have two uses of this cache MyCache<ImplA,String> and MyCache<ImplB,SomeType>.

7
  • 1
    What is Value, and how can it be ImplA and ImplB at the same time? Commented Dec 1, 2014 at 9:50
  • Sorry, I had changed the name of the parameter. I fixed the code now. Commented Dec 1, 2014 at 9:51
  • Still, the second question remains. Commented Dec 1, 2014 at 9:51
  • I want to say it can be one of those two types. I'm not clear on the syntax for that. Commented Dec 1, 2014 at 9:52
  • Then you would need a common base class. Commented Dec 1, 2014 at 9:53

2 Answers 2

2

I think what you're trying to achieve is something like this:

public abstract class Base<TKey>
{
    public Base(TKey key) { }
}

public class ImplA : Base<string>
{
    public ImplA(string key) : base(key) {}
}

public class MyCache<TBase, TKey> where TBase : Base<TKey>
{
    public TBase Get(TKey key)
    {
        return (TBase)Activator.CreateInstance(typeof(TBase), key);
    }
}

You can then call

var b = new MyCache<ImplA, string>().Get("hi");
Sign up to request clarification or add additional context in comments.

6 Comments

Okay, this part I have now, but how do I get the constraint on the Key parameter? Or do I even need one?
Not quite, I actually need to get a new instance of ImplA or ImplB, and I need to store that object. But maybe this could work if I extend IDoer.
I was unable to find a way to do the object constrution.
@edA-qamort-ora-y: It works with the new() constraint. Can you update your sample with your current code and exact problem?
@edA-qamort-ora-y I think now I figured out what you're trying to achieve. See edit.
|
1

You can't say to a generic class / method it should be Concrete A or B. You can only tell it it has a common denominator: a base class or an interface.

This is how it should look for example:

Interface:

interface IImpl {
    void SomeCommonMethod();
}

Generic class (here you tell T must implement the interface, so it can be any class that implements the interface). Also you have to tell it has a default constructor using the new constraint (as noted in comments, it is not possible to tell it has a parameter with type Key):

class MyCache<T,Key> : where T : IImpl, new()  {

Key classes:

class ImplA : IImpl {
   public ImplA( String key ) { }
}

class ImplB : IImpl {
   public ImplB( SomeType key ) { }
}

4 Comments

Okay, this part I have now, but how do I get the constraint on the Key parameter? Or do I even need one?
What do you expect T to be?
You can only have a type constraint on a parameterless constructor, new() is valid, new(key) is not.
@BenRobinson: That is a pity, but you are right. Updated.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.