While experimenting with C# 9 record, I came across a rather strange behavior. My record looks like this:
record MyRecord(Func<MyRecord> SomeAction, string Name)
{
public MyRecord(string name) : this(null, name)
{
SomeAction = Foo;
}
// Foo returns 'this' with SomeAction changed to Bar
MyRecord Foo()
{
Console.WriteLine("Foo: " + SomeAction.Method.Name);
return this with { SomeAction = Bar };
}
MyRecord Bar()
{
Console.WriteLine("Bar: " + SomeAction.Method.Name);
return this;
}
}
And I use it like this:
class Program
{
static void Main(string[] args)
{
var r = new MyRecord("Foo");
Console.WriteLine(r.ToString());
r = r.SomeAction();
r = r.SomeAction();
r = r.SomeAction();
}
}
The output I expected would be
Foo: Foo
Bar: Bar
Bar: Bar
However, the actual output I got:
Foo: Foo
Bar: Foo
Foo: Foo
Is this a bug or am I missing something?
Captures
Baron the original record, not the updated record. And on the original record,SomeAction.Method.NameisFoo. SinceBarreturnsthis, andBaris theBarof the original record, the second line returns the original record, which explains why the third line is the same as the first.It will be easier to understnd if we rewrite it like this:
To get your expected behavior, you would have to do something like this:
However I wouldn't recommend this approach - it is very difficult to follow.