Posts
51
Comments
117
Trackbacks
0
Advantage in creating a base non-generic class

In the project I'm working in, we use generics a lot - I mean a LOT!  Most of the classes we create are also generic types - it provides some niceties that way.  As the classes grew, eventually I got to a point where I want to put in a static function that doesn't deal with the generic type, something like below: 

public abstract class Container<T>

{

   private T _content;

 

   public T Content

   {

      get { return _content; }

      set { _content = value; }

   }

 

   public static void SomeStaticFunctionNotInvolvingT()

   {

      // Code here, but doesn't refer to T

   }

}

Unfortunately, I can't call the static function elegantly; I have to provide a type, before I can access it.  I can access it like this: Container<int>.SomeStaticFunctionNotInvolvingT(); - but it's a bit like cheating, and if/when the type parameter has constraints, it gets weird too since I have to use a type that can work.  So, the other possible solutions:

  1. Use a different class - this is the easy one, but sometimes you might just happen to have a proper named class (which happens to be generic), so you just want to put it there
  2. Create a non-generic base class as the parent of your generic class and put the method there.  This approach is also more inline with better class design - you only put the stuff that is needed where it is needed (no need to put a method that doesn't refer to T in a generic class)

I chose to pursue the second approach, and even though it works, I can't help but try to justify why I should do this - what advantage does this give me.  Looking back at my knowledge on how methods are shared in memory, only the data gets changed, I thought that if I use the method in the generic class, the method can't be shared - since each instance of that generic class for each type will result in a new copy being created in memory - at least for struct types.  .NET seem to imply that for object types, the framework will just create one for type object and use it all over.  How can I prove this?

So, I created a test function to see if that static function points to the same delegate (function pointer) or not as follows:

public abstract class Container

{

   public static void NonGenericBaseClassStaticFunction()

   {

      // Code here - no T reference at all (doesn't even know about T)

   }

}

 

public delegate void VoidFunction();

private void CompareDelegates()

{

   VoidFunction d1 = Container<int>.SomeStaticFunctionNotInvolvingT;

   VoidFunction d2 = Container<float>.SomeStaticFunctionNotInvolvingT;

 

   bool b = d1.Equals(d2);  // false

 

   VoidFunction d3 = Container<Window>.SomeStaticFunctionNotInvolvingT;

   VoidFunction d4 = Container<Button>.SomeStaticFunctionNotInvolvingT;

 

   b = d3.Equals(d4);  // false

 

   VoidFunction d5 = Container<int>.NonGenericBaseClassStaticFunction;

   VoidFunction d6 = Container<float>.NonGenericBaseClassStaticFunction;

 

   b = d5.Equals(d6);  // true

 

   VoidFunction d7 = Container<Window>.NonGenericBaseClassStaticFunction;

   VoidFunction d8 = Container<Button>.NonGenericBaseClassStaticFunction;

 

   b = d7.Equals(d8);  // true

   // Best way to invoke

   Container.NonGenericBaseClassStaticFunction();

}

The Container class above becomes the base class of the above Container<T> class.  If you run the test code, the first 2 Equals check will yield false, since even though it is a static function, the actual function pointer will differ.  The last 2 however, will yield true, since they're accessing the same actual function defined in the base class.  As a bonus, I can call the static function without specifying the generic type.

All in all, the above approach has some nice benefits:

  1. Cleaner class design - you put the function that you need where you need it.  Why put a function that doesn't need the generic type in a generic class?
  2. Invoking it from outside looks more normal, since you don't need to specify any type
  3. Better memory footprint - this is a bit debatable, but if you instantiate a lot of instances of the generic class with different types, each one will result in a different method pointer to the static method.  It is optimized somewhat, but by using the base class implementation, you don't have that overhead at all, since all references to that static method will now positively go to a single method location.
posted on Tuesday, February 05, 2008 6:38 PM Print
Comments
No comments posted yet.

Post Comment

Title *
Name *
Email
Url
Comment *  
 
News