C# 记录委托 属性
C# records with delegate property
在试验 C# 9 记录时,我遇到了一个相当奇怪的行为。我的记录是这样的:
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;
}
}
我是这样使用的:
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();
}
}
我预期的输出是
Foo: Foo
Bar: Bar
Bar: Bar
然而,我得到的实际输出:
Foo: Foo
Bar: Foo
Foo: Foo
这是一个错误还是我遗漏了什么?
return this with { SomeAction = Bar };
捕获 Bar
原始记录,而不是更新的记录。而在原始记录上,SomeAction.Method.Name
是 Foo
。由于Bar
returnsthis
,而Bar
是原始记录的Bar
,第二行returns是原始记录,这就解释了为什么第三行同第一行
这样改写会更容易理解:
class Program
{
static void Main(string[] args)
{
var r = new MyRecord("Foo");
Console.WriteLine(r.ToString());
var r1 = r.SomeAction(); // calls r.Foo, returns new instance of record, capturing r.Bar
var r2 = r1.SomeAction(); // calls r.Bar, and returns r.
var r3 = r2.SomeAction(); // calls r.Foo, returns new instance of record, capturing r.Bar
}
}
要获得预期的行为,您必须执行以下操作:
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);
MyRecord updated = null;
updated = this with { SomeAction = () => updated.Bar() };
return updated;
}
MyRecord Bar()
{
Console.WriteLine("Bar: " + SomeAction.Method.Name);
return this;
}
}
但是我不推荐这种方法 - 它很难遵循。
在试验 C# 9 记录时,我遇到了一个相当奇怪的行为。我的记录是这样的:
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;
}
}
我是这样使用的:
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();
}
}
我预期的输出是
Foo: Foo
Bar: Bar
Bar: Bar
然而,我得到的实际输出:
Foo: Foo
Bar: Foo
Foo: Foo
这是一个错误还是我遗漏了什么?
return this with { SomeAction = Bar };
捕获 Bar
原始记录,而不是更新的记录。而在原始记录上,SomeAction.Method.Name
是 Foo
。由于Bar
returnsthis
,而Bar
是原始记录的Bar
,第二行returns是原始记录,这就解释了为什么第三行同第一行
这样改写会更容易理解:
class Program
{
static void Main(string[] args)
{
var r = new MyRecord("Foo");
Console.WriteLine(r.ToString());
var r1 = r.SomeAction(); // calls r.Foo, returns new instance of record, capturing r.Bar
var r2 = r1.SomeAction(); // calls r.Bar, and returns r.
var r3 = r2.SomeAction(); // calls r.Foo, returns new instance of record, capturing r.Bar
}
}
要获得预期的行为,您必须执行以下操作:
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);
MyRecord updated = null;
updated = this with { SomeAction = () => updated.Bar() };
return updated;
}
MyRecord Bar()
{
Console.WriteLine("Bar: " + SomeAction.Method.Name);
return this;
}
}
但是我不推荐这种方法 - 它很难遵循。