具有委托属性的C#记录

具有委托属性的C#记录,c#,record,c#-9.0,C#,Record,C# 9.0,在试验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 M

在试验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
这是一个bug还是我遗漏了什么?

用{SomeAction=Bar}返回这个;
捕获原始记录上的
,而不是更新的记录。在原始记录上,
SomeAction.Method.Name
Foo
。由于
Bar
返回
this
,并且
Bar
是原始记录的
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);
        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();
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var r=新的MyRecord(“Foo”);
Console.WriteLine(r.ToString());
var r1=r.SomeAction();//调用r.Foo,返回记录的新实例,捕获r.Bar
var r2=r1.SomeAction();//调用r.Bar并返回r。
var r3=r2.SomeAction();//调用r.Foo,返回记录的新实例,捕获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);
        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();
    }
}
record MyRecord(Func SomeAction,字符串名)
{
公共MyRecord(字符串名称):此(空,名称)
{
SomeAction=Foo;
}
//Foo返回“this”,SomeAction更改为Bar
MyRecord Foo()
{
WriteLine(“Foo:+SomeAction.Method.Name”);
MyRecord updated=null;
updated=使用{SomeAction=()=>updated.Bar()}更新此文件;
更新的回报;
}
我的记录栏()
{
Console.WriteLine(“Bar:+SomeAction.Method.Name”);
归还这个;
}
}

但是,我不推荐这种方法-很难遵循。

当然,它们是实例方法:facepalm:。这让我意识到实现我想要的另一种方法是使用静态方法。