Software Tales from the Real World
Saturday, February 25, 2006
  Fun With Generics
.NET 2.0's Best New Language Feature It didn't take long after the release of .NET 2.0 for me to start finding all kinds of uses for what I consider to be the best new framework / language feature - generics. As a long-time C++ developer who used templates and the STL at every opportunity, I didn't realize how much I missed parameterized types until they were put back in my toolbox. I'm going to focus here on a concrete application of .NET generics and, in the process, point out some of their features and syntactic elements. For an excellent overview of .NET generics with comparisons to their counterparts in Java and C++, see Bruce Eckel's Interview with Anders Hejlsberg.

When templates first appeared in C++, one of their first applications was the creation of a reusable singleton class. The magazine C++ Report covered this topic in a number of articles, including John Vlissides' famous article entitled, "To Kill A Singleton". I recently needed a similar capability for a hierarchy of related classes which should each be singletons. Because these classes had inheritance relationships, using the new static class capability of .NET 2.0 wasn't appropriate. In this article, we'll build up to the solution I ultimately used.

Let's start with a very simple example:

namespace FunWithGenerics
{
public class Singleton1<T>
{
   public static T Instance
   {
       get { return instance_; }
       internal set { instance_ = value; }
   }

   static Singleton1()
   {
       Type typeT = typeof(T);
       Console.WriteLine("Singleton1 created for type '{0}'", typeT.Name);
   }

   private static T instance_;
}

public class Program1
{
   static void Main(string[] args)
   {
       Singleton1<int>.Instance = 5;
       Singleton1<string>.Instance = "Hello!";

       Console.WriteLine("Singleton<int>: Type='{0}', Instance='{1}'",
           typeof(Singleton1<int>).Name, Singleton1<int>.Instance);
       Console.WriteLine("Singleton<string>: Type='{0}', Instance='{1}'",
           typeof(Singleton1<string>).Name, Singleton1<string>.Instance);
   }
}
}
In this example, our singleton doesn't really do anything to ensure a single instance - we're just showing the basic syntax of a generic. The Singleton1 class is parameterized on any .NET type (intrinsic type, e.g. int; interface; class; etc.). In this case, the Main routine initializes two of these, one parameterized on an int, and another on a string. Because Singleton1 is not creating the instance it holds, Main must set the instance before its first use. The output when this program is run is: Singleton1 created for type 'Int32' Singleton1 created for type 'String' Singleton: Type='Singleton1`1', Instance='5' Singleton: Type='Singleton1`1', Instance='Hello!' We can see from the output that the static constructor on Singleton1 is called twice - there's really a different class instance for every distinct type on which Singleton1 is instantiated. At this point, the singleton class isn't very useful. But we have successfully created a generic class. If we now want to have the singleton generic class create the instance by simply changing the singleton's class static constructor as follows:
static Singleton2()
{
   instance_ = new T();
}
we'd get the following error: error CS0304: Cannot create an instance of the variable type 'T' because it does not have the new() constraint Here is where we encounter the first significant difference between .NET generics and C++ templates. In C++, no constraints on the type of class that can be used with a template are imposed until the template is instantiated for that type. So the above code (modified to be appropriate for C++) wouldn't cause an error until an instance of the template was created for a type which didn't have an accessible default constructor. In .NET, on the other hand, the generic class is validated when it is compiled. Therefore we must tell .NET something about the types which are allowed to be used with our singleton class:
public class Singleton2<T> where T : new()
{
   public static T Instance
   {
       get { return instance_; }
   }

   static Singleton2()
   {
       instance_ = new T();
   }

   private static T instance_;
}
Here we've used the "where" constraint specifier to tell .NET that only types which have a public default constructor - i.e. can be created by new T() - are allowed to be used as type parameters to Singleton2. At this point, if we try to use string as a type parameter, we get an error because string does not have a default constructor. For another example of where a constraint is required, consider this contrived case:
public class Singleton3<T> where T : new()
{
   public static T Instance
   {
       get { return instance_; }
   }

   static Singleton3()
   {
       Object o = new T();
       instance_ = o as T;
   }

   private static T instance_;
}
Here we're assigning the new T() to an Object reference and then casting that object reference to a T using the "as" operator. If we try to compile the above code, we get this error: error CS0413: The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint The singleton class needs to know that T is a reference type - one that's legal to use with the "as" operator. The class declaration instead needs to look like this:
public class Singleton3<T> where T : class, new()
Here we've told the compiler that T has be be a class and have a publicly accessible default constructor. If we try to create a singleton on an 'int', we get this error: error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'FunWithGenerics.Singleton3<T>' We've covered the basics. Now let's try to come up with real singleton functionality. A class which should be accessed only as a singleton can't have a public constructor - if it did, any code could create instances of the class at will. Let's define a simple class which should be accessed as a singleton:
public class OnlyWantOne4
{
   private OnlyWantOne4()
   {
   }

   public override string ToString()
   {
        return value_;
   }

   private string value_ = "OnlyWantOne4 says hello!";
}
This class has a private constructor, and we've already seen the error we get if we try to use this class with one of our current singleton classes: error CS0310: The type 'FunWithGenerics.OnlyWantOne4' must have a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'FunWithGenerics.Singleton4<T>' Here's where some of our earlier work is put to use. We can use reflection to create a T:
public class Singleton4<T> where T : class
{
   public static T Instance
   {
       get { return instance_; }
   }

   static Singleton4()
   {
       Type typeT = typeof(T);
       ConstructorInfo ci = typeT.GetConstructor(
           BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
       object o = ci.Invoke(null);
       instance_ = o as T;
   }

   private static T instance_;
}
In this version of our singleton, we've eliminated the new() constraint. Instead, we find the private constructor and use it to instantiate a T. Then we cast our instance_ variable to a T. Obviously, nothing prevents someone using our class from doing the same thing to create an OnlyWantOne4 instance. But the private constructor makes it pretty clear how it's to be used:
public class Program4
{
   static void Main(string[] args)
   {
       OnlyWantOne4 o = Singleton4<OnlyWantOne4>.Instance;

       Console.WriteLine("Singleton<OnlyWantOne4>: Type='{0}', Instance='{1}'",
           typeof(Singleton4<OnlyWantOne4>).Name, o);
   }
}
We're pretty close to a useful singleton generic class at this point. There's one refinement we can make. In the application where I needed this, my singleton class needed to do some initialization for any T on which it was instantiated. (It figured out what it needed to do based on custom attributes I put on the T classes.) To accomplish that, my singleton class had a private Initialize method:
public class Singleton5<T> where T : class
{
   public static T Instance
   {
       get { return instance_; }
   }

   static Singleton5()
   {
       Type typeT = typeof(T);
       ConstructorInfo ci = typeT.GetConstructor(
           BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
       object o = ci.Invoke(null);
       instance_ = o as T;
       instance_.Initialize();
   }

   private void Initialize()
   {
       // Do something based on what T is
   }

   private static T instance_;
}
The static constructor calls Initialize after creating the T instance. As it stands, this will yield the following error: error CS0117: 'T' does not contain a definition for 'Initialize' The compiler doesn't know that T has an Initialize method. In some ways it would seem like the private Initialize method on the singleton class is accessible, but it's not. Instead, we can change the constraint as follows:
public class Singleton5<T> where T : Singleton5<T>
Here we're requiring that any class that wants this singleton treatment be of the Singleton5<T> type - that is, derived from Singleton5<T>:
public class OnlyWantOne5 : Singleton5<OnlyWantOne5>
{
   private OnlyWantOne5()
   {
   }

   public override string ToString()
   {
       return value_;
   }

   private string value_ = "OnlyWantOne5 says hello!";
}
Here we've created a class that's to be treated as a singleton by deriving it from our singleton generic class. We can use it via:
public class Program5
{
   static void Main(string[] args)
   {
       OnlyWantOne5 o = OnlyWantOne5.Instance;

       Console.WriteLine("OnlyWantOne5: Type='{0}', Instance='{1}'",
           typeof(OnlyWantOne5).Name, o);
   }
}
Note the much simpler syntax - OnlyWantOne5.Instance instead of Singleton5<OnlyWantOne5>.Instance. There are some drawbacks to this approach, primarily that the concrete base class has been used. My experience is that singleton classes don't generally have inheritance relationships, but they could; and this would pose a problem in that case. I have some more interesting uses of generics I hope to post in the future. Let me know if you found this useful!
 
Comments:
this is completely awful
 
Very very good post for advanced programming!

Thaks for the info!
 
HI! Your forum is very interessing and my information will be good for you (I hope):)
anal sex movies
gaping anal sex
extreme anal sex
anal painful sex
anal porn sex
galleries anal sex
anal sex valley
anal sex pics
 
Absolutely interesting!!!

However I have an extra question. Could we instantiate a Type class passing 2 or 3 parameters to the constructor?

May be some trick with reflector, I don't know...

Thanks, and congratulations for your post!
 
Actually the parameterless constructor error had me baffled in my code till I read your take on it. Now I know the fix. Thanks!
 
Its a little dark and quite alarge place. One night I decided to follow my wife and see why she has to beout so late every night.
women in self bondage stories
xnxx stories big cock
nifty gay male stories
crossover stories adult
drunk porn stories
Its a little dark and quite alarge place. One night I decided to follow my wife and see why she has to beout so late every night.
 
Still, thiswas not the time nor the place to impress a woman, wife, and mother. Alice didnt think about it at the time, but they would have to move througha dozen kids watching a movie to get to any bedroom.
bare ass spanking stories
women masturbation stories
free beastiality audio stories
hot free preteen sex taboo stories
free hot and kinky sex stories
Still, thiswas not the time nor the place to impress a woman, wife, and mother. Alice didnt think about it at the time, but they would have to move througha dozen kids watching a movie to get to any bedroom.
 
Listen, I dont know who youpeople are, but if you do anything to hurt Angela, I swear to GodIll make you pay. Still, thiswas not the time nor the place to impress a woman, wife, and mother.
bdsm faggot boy stories
public masturbation stories
free xxx rated stories
oral sex stories
parent spanking kids stories
Listen, I dont know who youpeople are, but if you do anything to hurt Angela, I swear to GodIll make you pay. Still, thiswas not the time nor the place to impress a woman, wife, and mother.
 
We absolutely love your blog and find almost all of your post's to be exactly I'm looking for.
can you offer guest writers to write content for you? I wouldn't mind publishing a post or elaborating on some of the subjects you write concerning here. Again, awesome weblog!

Here is my website online shops für kleidung
 
Good article. I absolutely appreciate this website.
Stick with it!

my homepage Look At This
 
Good answer back in return of this difficulty with firm arguments and explaining everything concerning that.


Also visit my web site: all inclusive holidays
my web page > Look At This
 
Great post however , I was wondering if you could write
a litte more on this subject? I'd be very thankful if you could elaborate a little bit further. Cheers!

my web-site ... consolidate private student loans fixed rate
Also see my web site - bad credit home loan mortgage refinance
 
I think the admin of this web page is in fact working hard in favor of his web page,
as here every stuff is quality based information.


My blog ... preisvergleich private krankenkassen
 
I loved as much as you will receive carried
out right here. The sketch is tasteful, your authored subject matter stylish.
nonetheless, you command get got an nervousness over that you wish
be delivering the following. unwell unquestionably
come further formerly again since exactly the same nearly a lot
often inside case you shield this increase.

Take a look at my homepage :: click the up coming web site
 
I think the admin of this web site is in fact working hard in support of his web page, as here every
data is quality based information.

Feel free to surf to my page ... 울진금강소나무게시판 - 이복현님의 소광리 금강소나무 사진
 
Wow, marvelous blog layout! How long have you been blogging for?

you made blogging look easy. The overall look of your site is fantastic, as well as the content!



Visit my weblog - just click the up coming page
 
With havin so much written content do you ever run into any problems of plagorism or copyright violation?

My website has a lot of exclusive content I've either authored myself or outsourced but it appears a lot of it is popping it up all over the web without my authorization. Do you know any ways to help protect against content from being ripped off? I'd definitely appreciate it.



Feel free to visit my web page - More Information and facts
 
Link exchange is nothing else but it is only placing the other
person's web site link on your page at appropriate place and other person will also do similar in favor of you.

Here is my blog ... http://www.freedomkentucky.org/index.php?title=User:TerrellYo
 
Hi friends, its enormous post about educationand fully
defined, keep it up all the time.

Also visit my web-site: ratenkauf trotz Schufa
 
Thank you, I have just been searching for information about this topic for a long time and yours is the best I've found out till now. But, what about the bottom line? Are you certain in regards to the source?

Here is my web page: ava wiggins’s blog - ang-community
 
What's up, I want to subscribe for this web site to get hottest updates, so where can i do it please help out.

Check out my web blog ... work at home data entry
 
Amazing blog! Do you have any helpful hints for aspiring
writers? I'm planning to start my own site soon but I'm a little lost on everything.
Would you advise starting with a free platform like Wordpress or go for a paid option?

There are so many choices out there that I'm totally overwhelmed .. Any tips? Bless you!

Here is my homepage - Resources
 
Hi mates, good piece of writing and fastidious arguments commented here, I am actually enjoying by these.


My website click the following webpage
 
Pretty! This was an extremely wonderful post. Many thanks for providing these
details.

my site :: anything you Wanted to Understand Health care insurance - blag.wiki.aktivix.org
 
great publish, very informative. I'm wondering why the opposite specialists of this sector don't understand this.
You must continue your writing. I'm sure, you have a huge readers'
base already!

My web page :: Kredit Ohne BonitäT
 
WOW just what I was looking for. Came here by
searching for best buy fixed rate mortgage

Here is my blog post: Free affiliate
 
Hey there this is kind of of off topic but I was wanting to know if
blogs use WYSIWYG editors or if you have to manually code with HTML.
I'm starting a blog soon but have no coding skills so I wanted to get guidance from someone with experience. Any help would be enormously appreciated!

Also visit my blog post Reisen in die Türkei
 
There are many Infertility clinics available in almost every part of the world which offers various treatment methods to cure infertility.
On the other hand, men should have a nutritional balance, in order to improve the quality and quantity of their sperms that will fertilize the egg.
http://pregnancyhelper.in
 
male to female body massage in hyderabad One particular matter I seen immediately had been your own big difference Massage in Beijing rollers that will worked well a corner.
For those suffering with chronic pain, taking a risk with something that will possibly worsen the pain is definitely not the right choice.
http://hyderabad.locanto.in/ID_163682523/Male-to-Female-Body-Massage-in-Hyderabad.html
 
Post a Comment

Links to this post:

Create a Link



<< Home
Ramblings, observations, and editorials from my life as a real-world software developer.

ARCHIVES
February 2006 / March 2006 /


Powered by Blogger