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));

  1. 9 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

  6. Thank you for the interesting article.

    In the call to EnsureElementExists<T>, the compiler can infer <T> from Func<T> in the argument list, so you can simplify the call from this:

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

    To this:

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

    By JMG on Oct 13, 2010

  7. JMG,

    Good catch!

    Ade

    By Ade Miller on Oct 13, 2010

  1. 3 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.
  4. Apr 30, 2010: Tweets that mention An Alternative to the C# Generic new() Constraint | #2782 - Thinking about agile (small 'a') software development, patterns and practices for building Microsoft .NET applications. -- Topsy.com

Sorry, comments for this entry are closed at this time.