How does c# handle nested (generic) types?

AnorZaken

I'm trying to understand how C# views types in the face of nesting.
More specifically I'm trying to understand why some types are not considered assignment compatible or even castable, when there "kind of" only exist one definition of the nested class. Does the compiler / CLR actually generate different types for these, or what rules are at play exactly...

Example code:

public class Foo<T>
{
    protected class Private2 : Private1<Foo<T>>
    { }

    protected class Private1<T2> where T2 : Foo<T>
    {
        public sealed class Nested
        {
            public void Test(T2 foo)
            {
                foo.Method2(this); //Nope!
                var nes = (Private2.Nested)this; //Nope!
            }
        }
    }

    public void Method1()
    {
        var nested = new Private2.Nested();
        nested.Test(this);
    }

    private void Method2(Private2.Nested nested)
    {
        // something code...
    }
}

So even though the nested instance is created as a Private2.Nested it can not be casted to that type. And... well... how do the different Nested types relate to each other given that Nested is in fact sealed? (They can't be inheriting from each other right? But on the other hand their implementation should be 100% identical... am I wrong?)

Primary question: What exactly is the compiler doing when it "compiles" this nested class?? How many unique types (excluding valuetype-related) are actually generated, and if it is all the "same" type, is the restriction artificial (as in wouldn't an unsafe cast actually work)? (What I'm saying is that the IL for all these types comes from the same code definition - so at some level the compiler must know. Are instances of these types not bit-for-bit identical apart from their type-names?)


Secondary question: not what I'm really asking here, mostly for brevity / context: is there some simple change that would make the above work? Am I missing something obvious?

The type Foo<T> must never be directly referenced inside Private1<T2> - only use of T2 is allowed. Foo<T> is just my example stand in for nasty generic classes with 10~20 generic types. It's all just a "workaround" for not being able to alias a generic class with its types:

public class Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>
{
    //If only this was real...
    using BarT = Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>;

    public void Method1(BarT bar) { ... } //so good!!

    //goodbye readability... see you never...
    public void Method2(Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair> whatIsThisVariable) { ... }
}

Purpose: To avoid types of fields and method-parameters that are several screens wide and utterly unreadable! >:(

...As a side note I really wished this could be used as a type inside classes and interfaces, as in Private2 : Private1<this>. Well ok, that wouldn't work because it collides with extension syntax on methods, but something similar, perhaps <this>, <super>, <base> used like Method(<this> arg) or Private2 : Private1<<super>> ... kind of weird maybe.

user4003407

Consider this types:

public class Base {
    public static int Value;
    public class Nested { }
}
public class Derived:Base { }

What is Derived.Value and Derived.Nested. Actually, when you refer to inherited static members (nested class considered to be static member) thru derived class, you just reference base class members, so this have exactly same meaning as Base.Value and Base.Nested at compile time. There are no separate static field Derived.Value or separate class Derived.Nested.

public static void Test() {
    Derived.Value=10;
    Console.WriteLine(Base.Value);
    Base.Value=20;
    Console.WriteLine(Derived.Value);
    Base.Nested bn=new Derived.Nested();
    Derived.Nested dn=new Base.Nested();
    Console.WriteLine(typeof(Base.Nested).FullName);
    Console.WriteLine(typeof(Derived.Nested).FullName);
    Console.WriteLine(typeof(Base.Nested)==typeof(Derived.Nested));
}

Original answer:
Foo<A>.Private1<B>.Nested and Foo<C>.Private1<D>.Nested considered to be different types if A!=C or B!=D. They can share same implementation internally, but for assignment compatibility they are different. Foo<T>.Private2.Nested is just alias to Foo<T>.Private1<Foo<T>>.Nested. And even if class Bar:Foo<A>{}, classes Foo<A>.Private1<Foo<A>>.Nested and Foo<A>.Private1<Bar>.Nested still considered to be different types. So Foo<T>.Private1<T2>.Nested can not be converted to Foo<T>.Private1<Foo<T>>.Nested as T2 is not necessary Foo<T>.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to handle nullable types in generic class

From Dev

How does the SqlCommand handle parameters with integer types?

From Dev

How can I handle different types using generic type in swift?

From Dev

Writing a generic function in C, how to handle strings

From Dev

How compare classes with generic types in C#

From Dev

Using nested generic types in HashMap

From Dev

Should I avoid nested types in generic types?

From Java

Why does C# forbid generic attribute types?

From Dev

Autowiring based on generic types in Spring. How does it work?

From Dev

How does Scala handle Any to AnyVal covariance in method return types?

From Dev

Disadvantages of generic types in C #

From Dev

Generic mapping function to handle enumeration types

From Dev

How can I decrease verbosity when inheriting from C# generic types to non-generic types?

From Dev

Does Rust erase generic types or not?

From Dev

How Generic Types Are Instantiated

From Dev

With `CarrierWave::MimeTypes` deprecated, how should uploaders handle/overwrite generic content types?

From Dev

How would I write a generic function to handle multiple record types in ReScript?

From Dev

How does the C preprocessor handle circular dependencies?

From Dev

How does a repr(C) type handle Option?

From Dev

How does a repr(C) type handle Option?

From Dev

How to handle nested conditionals

From Dev

How to handle nested dicts?

From Dev

How to handle nested conditionals

From Dev

How to handle nested promises?

From Dev

How to handle nested observables

From Dev

Registering Nested Open Generic Types in Unity

From Dev

typeof(T) within generic nested types

From Dev

Registering Nested Open Generic Types in Unity

From Dev

What is the syntax for nested generic types in Genie?

Related Related

  1. 1

    How to handle nullable types in generic class

  2. 2

    How does the SqlCommand handle parameters with integer types?

  3. 3

    How can I handle different types using generic type in swift?

  4. 4

    Writing a generic function in C, how to handle strings

  5. 5

    How compare classes with generic types in C#

  6. 6

    Using nested generic types in HashMap

  7. 7

    Should I avoid nested types in generic types?

  8. 8

    Why does C# forbid generic attribute types?

  9. 9

    Autowiring based on generic types in Spring. How does it work?

  10. 10

    How does Scala handle Any to AnyVal covariance in method return types?

  11. 11

    Disadvantages of generic types in C #

  12. 12

    Generic mapping function to handle enumeration types

  13. 13

    How can I decrease verbosity when inheriting from C# generic types to non-generic types?

  14. 14

    Does Rust erase generic types or not?

  15. 15

    How Generic Types Are Instantiated

  16. 16

    With `CarrierWave::MimeTypes` deprecated, how should uploaders handle/overwrite generic content types?

  17. 17

    How would I write a generic function to handle multiple record types in ReScript?

  18. 18

    How does the C preprocessor handle circular dependencies?

  19. 19

    How does a repr(C) type handle Option?

  20. 20

    How does a repr(C) type handle Option?

  21. 21

    How to handle nested conditionals

  22. 22

    How to handle nested dicts?

  23. 23

    How to handle nested conditionals

  24. 24

    How to handle nested promises?

  25. 25

    How to handle nested observables

  26. 26

    Registering Nested Open Generic Types in Unity

  27. 27

    typeof(T) within generic nested types

  28. 28

    Registering Nested Open Generic Types in Unity

  29. 29

    What is the syntax for nested generic types in Genie?

HotTag

Archive