tags:

views:

49

answers:

2

A colleague of mine posted a question on an internal forum which got me thinking about whether this was possible through C#. Basically, he's got an interface as follows:

public interface IProvider<T>
{
    T GetT();
}

Is it possible to use something that implements that interface as a type parameter to another generic class and have access to the type T without re-specifying it? For example:

public class Foo<P> where P : IProvider<T>
{
    P p;

    T GetInnerT() { return p.GetT(); }
}

This does not compile, because the type T is not defined and hence can't be used as a parameter for IProvider. Is something like this even possible? Just curious!

+6  A: 

No, he'd need Foo to be generic in both P and T:

public class Foo<P, T> where P : IProvider<T>

otherwise there's no T for the IProvider<T> constraint to be aware of - the fact that it's part of the declaration of IProvider<T> is coincidental. The T in the above declaration is entirely separate (from the compiler's point of view) from the T in IProvider<T>. For example, this would be an equivalent declaration:

public class Foo<TProvider, TProvided> where TProvider : IProvider<TProvided>

Another thing to bear in mind is that an implementation of IProvider<T> could implement it multiple times, for different type arguments:

public class BigProvider : IProvider<string>, IProvider<int>, IProvider<char>

Now what would Foo<BigProvider> mean? It would be ambiguous... whereas with my declaration above, you'd do:

var x = new Foo<BigProvider, int>();

to mean the int-providing aspect of BigProvider.

Jon Skeet
+2  A: 

No, it's not possible, because your definition doesn't allow for the provision of type T when declaring Foo. Consider:

var x = new Foo<string>();

What is T in this case? There is no way to know at compile-time nor at runtime.

As you yourself said: the type T is not defined, and for the class to be valid you have to provide a means of definition. For example:

public class Foo<P, T> where P : IProvider<T>
Dan Puzey