Okay, lets split up your questions. First consider this simpler example,
without generics:

public class Outer
{
      public class Inner
      {
            public int field;
      }
}

In order to instantiate an object instance of the Inner class, you don't
need to have an object instance of the Outer class. The two are not tied
together in that fashion. So in C#, you write:

var obj = new Outer.Inner();
Console.WriteLine(obj.field);

Now on to generics.

public class Outer<T>
{
       public class Inner
       {
       }
}

In this case, members of the Inner class indeed have access to the 'T' type
parameter, because you can instantiate the Inner type like this:

var obj = new Outer<string>.Inner();

(Where T will obviously have the type value of System.String.)

Now in your example, you're right that the Third class does have access to
the type parameter 'T', because it is a nested type of Second<T>. Because
Third is declared as a static class, you cannot instantiate it, but you can
access its static field the following way:

Console.WriteLine(First.Second<string>.Third.field);

Now emitting the IL for this is not very trivial, you'll need to build some
more extension methods (mine only cover the most basic things, they don't
handle generic methods or nested types).
I would suggest you to compile example codes like these, and then check
their IL source with a reflector or ildasm. That's the most effective way of
learning.

2011/5/26 Stanislav <[email protected]>

> In first thank you so much for so useful reply!
>
> But I have next question:
>
> 1) If I have (for ex)
>
>  public static class First
>  {
>    public static class Second<T>
>    {
>      public static class Third
>      {
>        public static int field;
>      }
>    }
>  }
>
> then really I have following:
>
>  public static class First
>  {
>    public static class Second<T>
>    {
>      public static class Third<T>   <-- HERE
>      {
>        public static int _field;
>      }
>    }
>  }
>
> AND when I need to have access to field "_field" do I need to
> instanciate by generic only Third class type or I should instanciate
> base classes too? May be I should put T generic parameter of Second<T>
> as argument of Third?
>
> On 25 май, 14:03, Gábor Kozár <[email protected]> wrote:
> > Okay, that is VERY wrong.
> >
> > GenericParameters and GenericArguments are two distinct things.
> > Let me explain it to you with a simple example.
> >
> > Take this method definition:
> >
> > public static void Stuff<T>()
> > {
> >      ...
> >
> > }
> >
> > If you get the MethodDefinition object representing this method
> declaration,
> > it'll have a single item in GenericParameters: T. There are NO generic
> > arguments here, because the method does not known (or care) about what
> type
> > will be actually passed to it as T.
> > However, when you use this method:
> >
> > Stuff<string>();
> >
> > Here, in the IL, the 'call' instruction has an operand of type
> > GenericInstanceMethod (which derives from TypeSpecification, which
> derives
> > from TypeReference). It has the same GenericParameters as the definition
> > above (single item: T), but it also has a GenericArguments property,
> whose
> > items represent the types that were actually passed as type parameters to
> > the method (in this case, as T).
> > So the GenericArguments collection should have a single item here: a
> > reference to System.String.
> >
> > In short: T is the generic parameter, whereas string is the generic
> > argument. The same goes for types.
> > Hope it's clear now.
> >
> > 2011/5/25 Stanislav <[email protected]>
> >
> >
> >
> >
> >
> >
> >
> > > :) My mistake :))
> >
> > >        public static GenericInstanceType MakeGenericSelf(this
> > > TypeReference typeRef)
> > >        {
> > >            var genType = new GenericInstanceType(typeRef);
> > >            foreach (var p in typeRef.GenericParameters)
> > >                genType.GenericArguments.Add(p);
> > >            return genType;
> > >         }
> >
> > > On 25 май, 13:32, Gábor Kozár <[email protected]> wrote:
> > > > What is your MakeGenericSelf() extension method? I did not write it,
> I'm
> > > > quite positive about it (the linked code only contains various
> Reference*
> > > > extension methods, that I did write).
> >
> > > > Anyway, I see only one problem on this side (although you haven't
> shown
> > > the
> > > > code which emits the IL that actually uses the Utils class you inject
> > > here):
> >
> > > > utils = new TypeDefinition(declaringType.FullName, "<>_Utils",
> > > > TypeAttributes.NestedAssembly | TypeAttributes.Sealed |
> > > TypeAttributes.Class
> > > > | TypeAttributes.Abstract, declaringType.Module.GetType<Object>())
> > > >        {
> > > >              DeclaringType = resolvedType // here! DeclaringType
> should
> > > be
> > > > set to the original, generic TypeReference, NOT the resolved
> > > TypeDefinition
> > > >        };
> >
> > > > 2011/5/25 Stanislav <[email protected]>
> >
> > > > > I have a problem making generics. I cannot insert nongeneric class
> > > > > into generic class as nested. For ex:
> >
> > > > > Orriginally I have class GenericClass<T>
> >
> > > > >  public class Something
> > > > >  {
> > > > >    public class GenericClass<T>
> > > > >    {
> > > > >        public SomeProperty<T> { get; set; }
> > > > >    }
> > > > >  }
> > > > > but when I try to insert new nested class into GenericClass<T>, I
> > > > > whant to get result:
> >
> > > > >  public class Something
> > > > >  {
> > > > >    public class GenericClass<T>
> > > > >    {
> > > > >        private static class Utils
> > > > >        {
> > > > >            private static Utils() { /* ... */ }
> > > > >            public static string field;
> > > > >        }
> > > > >        public SomeProperty<T> {
> > > > >          get { return field; }
> > > > >          set { /* ... */ }
> > > > >        }
> > > > >    }
> > > > >  }
> >
> > > > > But in SomeProperty getter I have wrong accessing to GenericClass
> > > > > field:
> >
> > > > > Something.GenericClass<>.Utils.field;
> >
> > > > > generic class GenericClass<> is not instanciated by type.
> >
> > > > > How do I add nested type (here I use Gabor Kozar's method
> > > > > MakeGenericSelfhttp://pastebin.com/BTX3AvpV)?
> >
> > > > > var genericOwnerType = declaringType.HasGenericParameters ?
> > > > > declaringType.MakeGenericSelf() : null;
> > > > > var resolvedType = genericOwnerType == null ?
> > > > > declaringType.Resolve() : genericOwnerType.Resolve();
> >
> > > > > utils = new TypeDefinition(declaringType.FullName, "<>_Utils",
> > > > >                           TypeAttributes.NestedAssembly |
> > > > > TypeAttributes.Sealed | TypeAttributes.Class |
> > > > >                           TypeAttributes.Abstract,
> > > > > declaringType.Module.GetType<Object>())
> > > > >        {
> > > > >            DeclaringType = resolvedType
> > > > >        };
> >
> > > > >        resolvedType.NestedTypes.Add(utils);
> > > > >        var utilsCctor = new MethodDefinition(".cctor",
> > > > > MethodAttributes.SpecialName |
> > > > >                             MethodAttributes.RTSpecialName |
> > > > > MethodAttributes.HideBySig |
> > > > >                             MethodAttributes.Static,
> > > > > declaringType.Module.GetVoidType());
> >
> > > > > utilsCctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
> > > > >        utils.Methods.Add(utilsCctor);
> > > > >        m_utilsClasses.Add(declaringType, utils);
> >
> > > > > Whats wrong?
> >
> > > > > On 25 май, 07:23, Stanislav <[email protected]> wrote:
> > > > > > No, no, all is ok )))) Thank you very much for great help!
> >
> > > > > > On 24 май, 14:12, Gábor Kozár <[email protected]> wrote:
> >
> > > > > > > I agree, it's not very intuitive, but that's how it works. You
> may
> > > > > write
> > > > > > > extension methods, or use ones that I've shown in the
> discussion to
> > > > > ease the
> > > > > > > problem.
> > > > > > > If you can implement it better, please go ahead.
> >
> > > > > > > 2011/5/24 Stanislav <[email protected]>
> >
> > > > > > > > > when you Resolve() a TypeReference or MethodReference (or
> any
> > > > > > > > > other reference), you loose all generic arguments. You have
> to
> > > then
> > > > > > > > restore
> > > > > > > > > those generic arguments by essentially cloning the
> > > MethodReference
> > > > > (in
> > > > > > > > your
> > > > > > > > > case), except setting its DeclaringType to the original
> > > > > TypeReference
> > > > > > > > (which
> > > > > > > > > still contains the generic arguments).
> >
> > > > > > > > It looks like bug, not as feature )
> >
> > > > > > > > --
> > > > > > > > --
> > > > > > > > mono-cecil
> >
> > > > > --
> > > > > --
> > > > > mono-cecil
> >
> > > --
> > > --
> > > mono-cecil
>
> --
> --
> mono-cecil

-- 
--
mono-cecil

Reply via email to