views:

300

answers:

3

Ok. So I have a list of values, and I'd like to do something like the following:

MyObjectValues
.Select(currentItems=>new MyType()
{
     Parameter1 = currentItems.Value1,
     Parameter2 = currentItems.Value2
});

So here's the problem. I need the above example to work with named constructors, such as:

MyObjectValues
.Select(currentItems=>MyType.GetNewInstance()
{
     Parameter1 = currentItems.Value1,
     Parameter2 = currentItems.Value2
});

Is there any way I can do that? Basically, I have a static method I need to call to get the object instance back, and I'd like to initialize it as above.

EDIT: I don't have an easy way to modify the interface of MyType at present, so adding new function calls (while probably the 'best' approach) isn't very practical at the moment.

+2  A: 

I'm sure someone will think of a clever way to do it in pre 4.0 C#, but I just read Sam Ng's blog post on named parameters in C# 4.0. This should solve your problem. It would look like this:

MyObjectValues.Select(currentItems=>MyType.GetNewInstance(
    Parameter1:currentItems.Value1,
    Parameter2:currentItems.Value2));

EDIT

Fogot to mention, what makes this useful is that you can set defaults for the parameters, so you don't have to pass them all. The blog post is a good short summary.

Michael Meadows
That looks helpful, when it arrives.
GWLlosa
+1  A: 

Update: how about a factory:

MyObjectValues.Select(currentItems=>MyTypeFactory.GetNewInstance(currentItems.Value1,
currentItems.Value2));


public static class MyTypeFactory
{
    public static MyType GetNewInstance(
         typeofvalue1 value1, 
         typeofvalue2 value2)
    {
        return new MyType { Parameter1 = value1, Parameter2 = value2 };
    }
}
Peter Lillevold
I don't have an easy way to actually modify the implementation of MyType in this instance.
GWLlosa
With the factory you don't have to modify MyType, only implement MyTypeFactory
Peter Lillevold
+1  A: 

Unfortunately there's no direct support for this in C# 3.0. Object initializers are only supported for constructor calls. However, you might consider the Builder pattern. In my Protocol Buffers port, I support it like this:

MyType foo = new MyType.Builder {Parameter1 = 10, Parameter2 = 20}.Build();

So your example would become:

MyObjectValues.Select(currentItems => new MyType.Builder
{
     Parameter1 = currentItems.Value1,
     Parameter2 = currentItems.Value2
}.Build());

Of course, it means writing the nested Builder type, but it can work quite well. If you don't mind MyType being strictly speaking mutable, you can leave an immutable API but make an instance of Builder immediately create a new instance of MyType, then set properties as it goes (as it has access to private members), and then finally return the instance of MyType in the Build() method. (It should then "forget" the instance, so that further mutation is prohibited.)

Jon Skeet