-1

In C#, when you call a constructor, you can add one or more property initializers in curly braces:

var foo = new Bar() { Armpit = new Flapdoodle() { Limpet = 2 } };

What if that feature were generalized to "set properties on a return value":

var baz = foo.Armpit { Limpet = 4 };

This would be handy in cases like this:

var things = coll
    .Select(x => {
        var a = CreateA(x);
        a.Parent = this;
        return a;
    });

That's a common pattern in projecting collections via LINQ, but you see it elsewhere too: You have to declare a local variable and add some noise just to set one property on a return value before you pass it along to something else.

You write

f2(f1());

...but then whoops, something needs to change, so it becomes three lines:

A a = f1();
a.B = "c";
f2(a);

It seems like it might be nicer to be able to express the same code as follows:

var things = coll.Select(x => CreateA(x) { Parent = this } );

f2(f1() { B = "c" });

My question is this: Is this merely not useful enough to bother with, or is it actively a bad idea for some reason that's obvious to the C# team but not to me?

2 Answers 2

3

You've discovered a real problem when you want your code to consist of expressions rather than statements: you can't easily apply side effects to a value. However, introducing extra syntax is both inelegant and unncessary. Instead, I'd rather define a static helper function that can be used like

f2(With(f1(), a => { a.B = "c"; }));
var things = coll.Select(x => With(CreateA(x), a => { a.Parent = this; }));

where With would be implemented as With = (x, f) => { f(x); return x; }, i.e. the function is only evaluated for its side effects. This pattern allows side effects to be embedded into an expression.

0

Is this merely not useful enough to bother with, or is it actively a bad idea for some reason that's obvious to the C# team but not to me?

I can't think of any actively bad reason except perhaps the lack of atomicity (which also applies to the multi-line versions) but I think that it is not particularly useful. I've not had to do a lot of this, but then again, I dislike mutable types. Mostly though, I find this syntax to be mostly shuffling the deck chairs.

var a = f1();
a.B = "c";
f2(a);

Is about as readable as

f2(f1() { B = "c" });

to me. If anything, spreading the operations over multiple lines helps with the readability.

Sure, the select case is more compelling, but a select doing mutation strikes me as a bit smelly.

1
  • I think it's exceedingly smelly to use select to mutate items in a collection. In fact any feature that encourages it might qualify as "actively bad" on that basis alone, but projecting a collection is really a different case. Jan 7, 2016 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.