【问题标题】:Create class in Action<T> delegate在 Action<T> 委托中创建类
【发布时间】:2017-07-02 20:28:09
【问题描述】:

我知道这段代码不好,也许这是个愚蠢的问题,但谁能解释一下为什么它会以这种方式工作?

我有这个简单的课程

public class Customer
{
    public string Name { get; set; }
}

我还有下一个带有 Action 委托的方法

private Customer GetCustomer(Action<Customer> action)
{
    var model = new Customer { Name = "Name 1" };
    action?.Invoke(model);

    return model;
}

然后我用委托执行这个方法并写入控制台model.Name

var model = GetCustomer(c => c = new Customer { Name = "Name 2" });
Console.WriteLine(model.Name);

我希望得到“名称 2”。但我得到“名称 1”——这是在方法内部定义的类的值。我明白为了得到我想要的——我可以这样写代码:

var model = GetCustomer(c => c.Name = "Name 2");
Console.WriteLine(model.Name);

一切都会好起来的。但是为什么我的第一个实现不起作用? 如果有人向我解释这一点,我将不胜感激。

【问题讨论】:

  • 方法实例没有被替换,你不能在 lambda 中这样做。
  • c 是对model 的引用的副本。分配c = new ...c 将引用另一个实例

标签: c#


【解决方案1】:

您的 lambda 中的c 仅分配给参数,它不会将其分配回GetCustomer 中的model

【讨论】:

    【解决方案2】:

    您的例子中的 Lambda 表达式编译成一个方法。
    也一样,为什么这段代码不会变c.Name

    // code below is equivalent of
    // c => c = new Customer { Name = "Name 2" }
    private void Foo(Customer c)
    {
        // c will be changed inside method,
        // but will remain unchanged outside it
        c = new Customer { Name = "Name 2" };
    }
    

    【讨论】:

      【解决方案3】:

      在您的 lambda 表达式中,您只是说 cmodel 指向同一个引用。然后您正在更改c 的引用。最后model 仍然引用前一个实例。这是您尝试执行的等效代码:

      var model = new Customer { Name = "Name 1" };
      var c = model;
      c = new Customer { Name = "Name 2" };
      

      但是,model.Name 仍然是 Name1

      您可以像更改 hte 属性之一一样更改代码:

       var model = GetCustomer(c => c.Name = "Name2");
       Console.WriteLine(model.Name);
      

      【讨论】:

        【解决方案4】:
        var model = GetCustomer(c => c.Name = "Name 2");
        

        代替:

        var model = GetCustomer(c => c = new Customer { Name = "Name 2" });
        

        为什么?因为您想对在新函数中传输的同一个实例进行更改(实现委托)。如果您在新函数 (c) 中创建 Customer 的新实例,那么它将对 Customer 的新实例进行更改,这在 c 结束时将无效。

        here 相同,但使用List

        【讨论】:

        • 嗯,他在原始帖子中有这个。
        • 如果你解释一下为什么这会回答这个问题,这将是一个更好的答案 - 但我认为你在 OP 正在寻找的东西上走在正确的轨道上。
        猜你喜欢
        • 1970-01-01
        • 2011-01-17
        • 2011-05-27
        • 2012-09-09
        • 2011-03-02
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多