18

Suppose we have a nested generic class:

public class A<T> {
    public class B<U> { }
}

Here, typeof(A<int>.B<>) is in essence a generic class with two parameters where only the first is bound.

If I have a single class with two parameters

public class AB<T, U> { }

Is there a way to refer to "AB with T=int and U staying open"? If not, is this a C# limitation, or a CLR limitation?

GregC
  • 7,737
  • 2
  • 53
  • 67
configurator
  • 40,828
  • 14
  • 81
  • 115

3 Answers3

10

Apparently it can't be done in C#, you have to specify either both type parameters, or none.

And it doesn't seem to be supported by the CLR either, A<int>.B<> and A<string>.B<> refer to the same type:

Type t1 = typeof(A<int>).GetNestedType("B`1");
Type t2 = typeof(A<string>).GetNestedType("B`1");
// t1.Equals(t2) is true

The enclosing type of both types is A<> (open generic type)

EDIT: further testing shows that typeof(A<int>.B<string>) is actually a generic type of arity 2, not a nested generic type of arity 1... typeof(A<int>.B<string>).GetGenericArguments() returns an array with typeof(int) and typeof(string). So typeof(A<int>.B<>) would actually be equivalent to (A.B)<int, >, which isn't supported (a generic type can't be partially closed)

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • 4
    Your observation is correct. Under the covers, C.D is just "C.D". The C# way of conceiving of it as C.D is just a convenient fiction. – Eric Lippert Apr 09 '11 at 01:22
  • 1
    @Eric, thanks for the confirmation. I was hoping you would see this question and shed some light on it... It could be a good subject for a blog post if you're out of ideas ;) – Thomas Levesque Apr 09 '11 at 01:29
  • You're right, of course. My mistake was assuming that `typeof(A.B<>)` would be legal - I knew that `A.B` is implemented as `A.B`, meaning that `typeof(A.B<>)` would actually be `A.B` which didn't seem like it should be legal. – configurator Apr 09 '11 at 03:24
2

Is this what you have in mind?

   class AB<T, U>
   {
      protected T t;
      U u;
   }

   class C<U> : AB<int, U>
   {
      public void Foo()
      {
         t = 5;
      }
   }
GregC
  • 7,737
  • 2
  • 53
  • 67
  • 1
    @downvoter: talk to me. Would you like to see reflector output, C# specification excerpt, something else? – GregC Apr 09 '11 at 00:01
  • 2
    It looks like the OP is asking for an instance of a `Type` object that expresses something like `typeof(AB)`. – Gabe Apr 09 '11 at 01:15
-1

you can use the Func<int,int> generic to pass multiple parameters as a single function returning an type. Curried many to pass many arguments as a single parameter.

 [Fact]
    public async Task TestCurried()
    {
        Func<int, Func<int, int>> curried = x => y => x + y;
        int sum = curried(1)(3);
        Assert.Equal(sum.ToString(), "4");
    }
see
https://blog.tchatzigiannakis.com/generics-as-super-functions/
Golden Lion
  • 3,840
  • 2
  • 26
  • 35