edA-qa mort-ora-y
edA-qa mort-ora-y

Reputation: 31861

Dependent type constraints in generic class with multiple parameters

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>.

Upvotes: 1

Views: 1222

Answers (2)

dav_i
dav_i

Reputation: 28107

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");

Upvotes: 2

Patrick Hofman
Patrick Hofman

Reputation: 156948

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 ) { }
}

Upvotes: 1

Related Questions