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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.