An Alternative to the C# Generic new() Constraint

Monday, November 12, 2007 – 3:33 pm

Here’s something I came up with other the weekend while playing with some code…

I wanted to write a method that ensured that some object of type T was always available.

    ModelElement element = EnsureElementExists<ModelElement>(_store);

Unfortunately in this case the ModelElement class does not have a parameterless constructor. This means I can’t use the where T:New() constraint and then just create a new instance in my generic method. What I can do is use a delegate to provide a new instance of the object if I need it:

    public delegate T ConstructorDelegate<T>() where T : class; 

    public static T EnsureElementExists<T>(Store store, ConstructorDelegate<T> ctor)
        where T : ModelElement
    {
        T element = store.GetElement<T>(); 

        if (element == null)
            element = ctor(); 

        return element;
    }

This means I can now write code like this where DiagramElement (a class derived from ModelElement) is created by the delegate:

    DiagramElement diagramElement = EnsureElementExists<DiagramElement>(_store,
        delegate()
        {
            return new DiagramElement(_store);
        });

Calls to EnsureElementExists can use the anonymous delegate to create a new DiagramElement with a parameterized constructor.

March 2009 Update: Cleaner syntax using lambdas

I was playing around with this again recently and realized that  lambda expressions can make the syntax you need to use much simpler and remove the need to define a ConstructorDelegate.

    public static T EnsureElementExists<T>(Store store, Func<T> ctor)
        where T : ModelElement
    {
        T element = store.GetElement<T>(); 

        if (element == null)
            element = ctor(); 

        return element;
    }

The calling code is further simplified:

    DiagramElement diagramElement = EnsureElementExists<DiagramElement>(_store,
        () => new DiagramElement(_store));

Share on:
  • Digg
  • DZone
  • del.icio.us
  • TwitThis
  • Live
  • Google Bookmarks
  1. 6 Responses to “An Alternative to the C# Generic new() Constraint”

  2. Nifty idea…the only thing I’m wondering about is why you have a where constraint on ConstructorDelegate. It seems like that would overtly constraint your open-ended solution.

    And just to be nitpicky…wouldn’t you add the object you just created in your if block so you wouldn’t keep creating it?

    Again, good idea - I like this :)

    By Jason Bock on Nov 13, 2007

  3. Nice catch Jason,

    I’ve updated the code to reduce the constraint on ConstructorDelegate and fixed the if statement.

    Ade

    By Ade on Nov 13, 2007

  4. Why not use this?
    (T)typeof(T).GetConstructor(

    By dreamxpert on May 23, 2009

  5. dreamxpert,

    You could use this approach. I prefer the inversion of control pattern where EnsureElementExists knows nothing about how to create an instance of T and relies on the delegate.

    I’d also we wary of using GetConstructor() as now you’re using reflection which is likely to be slower than calling a delegate.

    Ade

    By Ade Miller on May 25, 2009

  1. 2 Trackback(s)

  2. Nov 14, 2007: #2872 » Blog Archive » Windows Live Writer
  3. Mar 13, 2009: An Alternative to the C# Generic new() Constraint using Lambdas | #2782 - Agile software development, patterns and practices for building Microsoft .NET applications.

Post a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word