I run into this scenario frequently. At first glance, I think, “That’s poor coding; I’m executing a method twice and necessarily getting the same result.” But upon thinking that, I have to wonder if the compiler is as smart as I am and can come to the same conclusion.
var newList = oldList.Select(x => new Thing {
FullName = String.Format("{0} {1}", x.FirstName, x.LastName),
OtherThingId = x.GetOtherThing() != null : x.GetOtherThing().Id : 0 // Might call x.GetOtherThing() twice?
});
Does the behavior of the compiler depend on the contents of the GetOtherThing
method? Say it looks like this (somewhat similar to my real code right now):
public OtherThing GetOtherThing() {
if (this.Category == null) return null;
return this.Category.OtherThings.FirstOrDefault(t => t.Text == this.Text);
}
That will, barring very poorly handled asynchronous changes to whatever store these objects are coming from, definitely return the same thing if run twice in a row. But what if it looked like this (nonsensical example for the sake of argument):
public OtherThing GetOtherThing() {
return new OtherThing {
Id = new Random().Next(100)
};
}
Running that twice in a row would result in the creation of two different objects, with different Ids in all likelihood. What would the compiler do in these situations? Is it as inefficient as it seems to do what I showed in my first listing?
Doing some of the work myself
I ran something very similar to that first code listing and put a breakpoint in the GetOtherThing
instance method. The breakpoint was hit once. So, it looks like the result is indeed cached. What would happen in the second case, where the method might return something different each time? Would the compiler optimize incorrectly? Are there any caveats to the result that I found?
EDIT
That conclusion was invalid. See comments under @usr’s answer.