4

I have a class :

class MyClass 
{
   public static class MyNestedClass 
   {
       public const int M1 = 1;
       public const int M2 = 2;
   }
}

class MyClass2 
{
   public static class MyNestedClass 
   {
       public const int M1 = 1;
       public const int M2 = 2;
   }
}

and a generic function :

private static void Work<T>()
{
    Type myType = typeof(T.MyNestedClass);
    myType.GetFields().Select(....);
    // .. use T here as well..
}

I get error : error CS0704: Cannot do member lookup in 'T' because it is a type parameter.

Since MyNestedClass is static class, when i try to pass it as another Generic Type argument as :

private static void Work<T, S>()
{
    Type myType = typeof(S);
    myType.GetFields().Select(....);
    // .. use T here as well..
}

calling via,

Work<MyClass, MyClass.MyNestedClass>();

gives me error : static types cannot be used as type arguments

What is the right way to access nested static and non-static class in c# ?

Ashish Negi
  • 5,193
  • 8
  • 51
  • 95
  • `private static void Work() where T: MyClass` don't know if this can work too :) – CodeNotFound Jun 14 '18 at 13:45
  • @CodeNotFound I have multiple classes all of which has `MyNestedClass` inside it. use case : EventProvider and `Tasks` is static inner class. – Ashish Negi Jun 14 '18 at 13:46
  • I will read [this](https://stackoverflow.com/questions/1083032/why-would-i-ever-need-to-use-c-sharp-nested-classes) then. – CodeNotFound Jun 14 '18 at 13:47
  • "I have multiple classes all of which has MyNestedClass inside it". Do you? How is the compiler supposed to know this? – mm8 Jun 14 '18 at 13:50
  • 1
    Why are you even using nested classes here? That seems like a horrible code smell to me. – DavidG Jun 14 '18 at 13:51
  • 1
    Static types can't be used as generic arguments. You can't do `List`... Even if `MyNestedClass` wasn't nested it wouldn't change anything. – xanatos Jun 14 '18 at 13:52
  • `EventSource` in c# dictates to have nested class `Task` with multiple `EventTask ` inside it. https://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource(v=vs.110).aspx Similarly EventProvider in my case. – Ashish Negi Jun 14 '18 at 13:53
  • If i remove `static` from class, will `T.MyNestedClass` help ? – Ashish Negi Jun 14 '18 at 13:55
  • 1
    Bear in mind that wherever you identify a *type* by name in your code, the compiler has to identify *the type that you're talking about* and put a token into the IL that identifies the specific type - which will either be a concrete type or a generic type parameter. When you say something like `A.B.C` then the type token that gets emitted is for `C`. It's **not** "first find type/namespace `A`, then *separately* find a `B` within it and then find a `C` within *that*. – Damien_The_Unbeliever Jun 14 '18 at 13:55
  • @mm8 I thought a way to enforce by `constraints`. – Ashish Negi Jun 14 '18 at 13:55
  • That MSDN link is not great code. The nested type could quite easily be `private` for example, but there is no gain for it to be a nested class. – DavidG Jun 14 '18 at 13:56
  • @DavidG It can't be private as it's used by EventSource to generate dynamic manifests. – Ashish Negi Jun 14 '18 at 13:57
  • And i totally agree it's not great code, but not nesting is not an option for me. – Ashish Negi Jun 14 '18 at 13:58
  • 1
    @AshishNegi: You can't use constraints to enforce a type to have a nested type... – mm8 Jun 14 '18 at 13:58
  • The Generic is pointless here. It's doing nothing, just replace `T` with `MyClass` – Liam Jun 14 '18 at 14:13

1 Answers1

3

The type T has no nested type called MyNestedClass unless you specify T to actually be a MyClass. You can then use the GetNestedTypes() method to retrieve the nested type:

private static void Work<T>() where T : MyClass
{
    Type myType = typeof(T).GetNestedTypes().FirstOrDefault();
    //...
}

There is a GetNestedType method that accepts a type name string available as well.

But you can't use constraints to enforce a specific type to have a nested type.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • GetNestedType("Tasks") is better, if i have to use reflection. – Ashish Negi Jun 14 '18 at 13:49
  • 1
    If `T : MyClass` what's the point in the generic at all? You might as well just use `MyClass` in place of `T`? – Liam Jun 14 '18 at 14:12
  • @Liam: Yes, unless MyClass is some kind of base class or interface. – mm8 Jun 14 '18 at 14:14
  • @Liam i have multiple classes with same nested class. Real world use case : Multiple `EventSource` and `Tasks` nested class. – Ashish Negi Jun 14 '18 at 14:19
  • *"you can't use constraints to enforce a specific type to have a nested type..."* +1 – Glenn Slayden Aug 22 '20 at 03:29
  • Oh, and by the way (since it hasn't been mentioned elsewhere on this page), from the perspective of the nested (or "enclosed") type, its containing ("outer") type can be discovered via its `Type.DeclaringType` property... – Glenn Slayden Oct 18 '20 at 19:51