Rune Jensen
Rune Jensen

Reputation: 761

Is it possible to use generic parameter from another generic type

Is it possible to use generic parameter from another generic type, and infer the usage where used like this:

public class TypeA<T2> { }

public class TypeB<T1, T3, T2> where T3 : TypeA<T2> {}

public class Test
{
    public Test()
    {
        // works but kind of ugly...
        new TypeB<string, TypeA<int>, int>();

        // Is it possible somehow to infer the TypeAType from the implemented generic generic type so I can use it like this?
        new TypeB<string, TypeA<int>>();
    }
}

Upvotes: 3

Views: 1786

Answers (2)

Good Night Nerd Pride
Good Night Nerd Pride

Reputation: 8452

The short answer is no, because C# does not support "generics on generics".

To explain what that means let me show you are more concrete example:

List<int> list = new List<int>();
HashSet<int> set = list.To<HashSet<int>>();

Here, the extension method To() is a magical piece of code that can convert one type of container into another.

Assuming C# supported this feature, one would naively try to define that method like so:

public static class EnumerableExtensions {
    public static TContainer<TItem> To<TContainer<TItem>>(
        this IEnumerable<TItem> source)
        where TContainer: IEnumerable {
        // magic
    }
}

This of course won't compile, because C# cannot parse a generic type parameter that is generic itself (TContainer<TItem>).

This whole concept is called higher kinded polymorphism (or higher kinded types) which C# doesn't support. It might in the future though and you can track progress in this GitHub issue.

There is a Nuget package called LanguageExt which provides some higher-kinded types and if I recall correctly it does the same thing you do: explicitly declare the inner type so the type inference can use it.

Upvotes: 3

Jeremy Lakeman
Jeremy Lakeman

Reputation: 11100

You can get close by introducing another type, with the same name, but with fewer constraints. To use in this situation;

public class TypeB<T1, T3, T2> where T3 : TypeA<T2> {}
public class TypeB<T1, T2> : TypeB<T1, TypeA<T2>, T2> {}

new TypeB<string, int>();

See also UserStore<...> from AspNetCore.Identity.

Upvotes: 0

Related Questions