Michael McMullin
Michael McMullin

Reputation: 1470

Implying one generic type parameter from another in C# class

Suppose I have a class like this:

public class Demo<A, B>
    where A : IEquatable<A>
    where B : IList<A>, new()
{
    ...
}

Creating an instance is easy enough:

Demo<string, List<string>> test1 = new Demo<string, List<string>>();
// or more concisely:
var test2 = new Demo<string, List<string>>();

My question is: Can class Demo be rewritten without explicitly requiring type A when creating an instance, where it's implied somehow through type B? Something like this (which obviously doesn't work):

public class Demo<B>
    where B : IList<A>, new()
        where A : IEquatable<A>
....

var test = new Demo<List<string>>(); // Only one type parameter

It's not a big deal for the particular project I'm working on, but the repetition of type parameters needed to create an instance piqued my curiosity.

EDIT
Thanks for all the suggestions, it's clarified the problem a lot better for me. I suppose I could rephrase the question as: can a generic class access the generic type parameter of its constraint's generic type?

So is it possible to create something along the lines of:

public IMyInterface<T> where  T : IEquatable<T>...
public class myClass<A> where A : IMyInterface<B>, new()... // doesn't compile

...and access both A and B in my code? I suspect not.

Upvotes: 1

Views: 397

Answers (3)

Reza
Reza

Reputation: 19933

public class BaseDemo<A, B>
    where A : IEquatable<A>
    where B : IList<A>, new()
{
}

public class Demo<B> : BaseDemo<B, List<B>>
    where B : IEquatable<B> 
{
}

usage

var test2 = new Demo<string>();

see this working fiddle

Upvotes: 0

Seb T.
Seb T.

Reputation: 1124

It is a bit tricky to figure out without knowing the real content of the Demo class, but why would you need to consider the List as generic parameter ?

Why not simply

public class Demo<A> where A : IEquatable<A>
{
    public Demo()
    {
       DemoB = new List<A>();
    }

    public Demo(A demoA) : this()
    {
        DemoA = demoA;            
    }

    public A DemoA { get; }
    public IList<A> DemoB { get; }
}

Upvotes: 0

Janne Matikainen
Janne Matikainen

Reputation: 5121

You can define an intermediate interface that will do your type mappings between A and B

public interface IDemo<A, B> 
    where A : IEquatable<A>
    where B : IList<A>, new()
{

}

And then define your Demo class as such.

public class Demo<B> : IDemo<B, List<B>>
    where B : IEquatable<B> // This is required for this type definition
{

}

Which can then be used like you wanted

var demo = new Demo<string>();

Upvotes: 2

Related Questions