Home > syntax, wish > General form of C# Object Initializers

General form of C# Object Initializers

C# has a language feature that allows several properties of an object to be assigned to as a suffix to a new expression, namely the object initializer:

var myObj = new MyClass
{
    SomeProperty = 5,
    Another = true,
    Complain = str => MessageBox.Show(str),
};

As properties can have hand-coded setters, this is an opportunity to call several methods on the newly constructed object, without having to make each method return the same object.

The limitations on property setters are:

  • They can only accept one argument
  • They cannot be generic

I would like it if we could call methods and enlist in events, as well as assign to properties, inside an object initializer block.

var myObj = new MyClass
{
    SomeProperty = 5,
    Another = true,
    Complain = str => MessageBox.Show(str),
    DoSomething(),
    Click += (se, ev) => MessageBox.Show("Clicked!"),
};

And why should such a block of modifications only be applicable immediately after construction? We could have:

myObj with
{
    SomeProperty = 5,
    Another = true,
    Complain = str => MessageBox.Show(str),
    DoSomething(),
    Click += (se, ev) => MessageBox.Show("Clicked!"),
}

The with would be a new keyword that operates on an object of some type and produces the same object and type – note that this would be an expression, not a statement.

So you could use initializer-style syntax regardless of whether you’d got the object from a new expression or from an IOC or factory method, etc.

In fact you could use with after a complete new and it would be equivalent to the current style of object initializer:

var myObj = new MyClass() with
{
    SomeProperty = 5,
    Another = true,
    Complain = str => MessageBox.Show(str),
    DoSomething(),
    Click += (se, ev) => MessageBox.Show("Clicked!")
};

I mused about this in a Stack Overflow answer, and Charlie Flowers pointed out something I should have realised immediately – we can implement with as an extension method.

public static T With(this T with, Action<T> action)
{
    if (with != null)
        action(with);
    return with;
}

Equivalent of normal object initializer, but with event enlisting:

var myObj = new MyClass().With(w =>
{
    w.SomeProperty = 5;
    w.Another = true;
    w.Click += (se, ev) => MessageBox.Show("Clicked!");
};

And on a factory method instead of a new:

var myObj = Factory.Alloc().With(w =>
{
    w.SomeProperty = 5;
    w.Another = true;
    w.Click += (se, ev) => MessageBox.Show("Clicked!");
};

I couldn’t resist giving it the “maybe monad”-style check for null as well, so if you have something that might return null, you can still apply With to it and then check it for null-ness.

About these ads
Categories: syntax, wish Tags: ,
  1. Marcel
    April 10, 2009 at 9:44 am

    Chel’nak! (Cool :D)

  2. Jason Hammer
    May 12, 2009 at 9:24 pm

    I love this idea, very simple execution as well.

  3. June 3, 2010 at 6:09 pm

    I really like this solution, it appears you would be interested in the maybe project http://maybe.codeplex.com ? either way I’d love to hear your thoughts on it.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: