Home > front end >  Is it possible to use generic parameter from another generic type
Is it possible to use generic parameter from another generic type

Time:09-17

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>>();
    }
}

CodePudding user response:

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.

CodePudding user response:

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.

  • Related