tags:

views:

44

answers:

2

Breaking down the MS RBTree (an internal .Net abstract class), I have discovered that one method returns TreePage<K>:

private TreePage<K> AllocPage(int size)
{
    ...
}

Within the method, variables are declared as TreePage...but the class is not defined that way:

private sealed class TreePage
{
    ...
}

Yet, when I mimic the code and definition using .Net 2010 (Express), I cannot do this:

Error: The non-generic type 'RBTree.TreePage' cannot be used with type arguments

So, is there an extension method that I can't find? Is there something MS is doing that we just don't get to see?

+4  A: 

When you declare a class nested in a generic class

class Foo<T>
{
    class Bar
    {
    }
}

this gets compiled to a class

Foo<T>

and a class

Foo+Bar<T>

Bar is generic, because it is nested in the generic class Foo. But the type parameter declaration is not repeated in C# (where you refer to the class as Foo<T>.Bar).

I noticed that Reflector shows the generic type parameter for classes nested in generic types, even if they don't have declared any type parameters directly. That's a bug. You need to fix the code when copy it straight out of Reflector.

dtb
@dtb: so, Reflector is showing me TreePage<K>...what you're saying is, then, that I should remove any generic <K> type arguments and it should be okay?
dboarman
@dtb, I'm not sure I understand how this addresses the OP's question though? (I think Logan nailed it.)
Kirk Woll
@dboarman: if you got your code from Reflector and there is no generic TreePage to be found, then, yes, you've stumpled upon a bug and you need to remove the <K>.
dtb
A: 

It's actually less complicated than you might imagine. Klass and Klass<T> are two completely different types. To wit:

  class A
  {
  }

  class A<T>
  {}

  class Program
  {
    static public void Main(string[] args)
    {
      A a = new A();
      A<int> generic_a = new A<int>();
    }
  }

There's another TreePage<T> floating around there somewhere.

Logan Capaldo
+1, this often catches people by surprise.
Kirk Woll
However, Reflector is not seeing 2 classes. When I search for `TreePage`, it responds with `TreePage<K>`. When I select to disassemble this class, it is defined exactly as I showed in my question.
dboarman
@dboarman I didn't know you were using reflector (you didn't mention that in your question), I assumed you were looking at source. As dtb mentioned, reflector does have bugs.
Logan Capaldo
This would not work the way it is intended. For instance, I would not be able to add objects of type `A` to an `A<K> []` array.
dboarman
@Logan: not to be terse, but how else would I be able to break *'down the MS RBTree (an internal .Net abstract class)'* as I stated in the first line of my question? ;)
dboarman
Intended by who? I was merely explaining how you could have code like `class X { X<T> Foo() { ... } }`. Of course you didn't actually have code like that. You can always look at the CIL instead of the reconstructed C#, that will never lie to you (even in cases where the "lying" isn't a bug, like when a feature that isn't present in C# was used like VB.NET's When on catch statements).
Logan Capaldo
@dboarman http://msdn.microsoft.com/en-us/library/cc667410.aspx
Logan Capaldo