【问题标题】:In C#, what are some rules of thumb for _where_ to clone objects?在 C# 中,_where_ 克隆对象的一些经验法则是什么?
【发布时间】:2015-06-17 22:30:37
【问题描述】:

情况如下:我正在尝试确定克隆对象的 where 部分以避免修改原始对象。

我有两个选择:

  • 调用者中克隆对象并将克隆的对象传递给方法(“被调用者”),从而防止被调用者进行潜在的修改。
  • 被调用者中克隆对象,因为被调用者修改了它传递的对象,这假设调用者从不希望修改参数对象。

我找到了这个 6 岁的答案,有各种各样的意见。不幸的是,似乎并没有达成真正的共识。

Passing copy of object to method -- who does the copying?

这是我的代码形式的问题:

  • 我是否在调用者中克隆对象并将克隆的对象传递给方法?
public static void Main()
{
    var foo = new Foo();
    Bar.Baz(foo.DeepClone());
}

public static class Bar
{
    public static void Baz(Foo foo)
    {
        /* ... modifies members in foo ... */
    }
}

public class Foo { /* ... */ }
  • 我是否在被调用者中克隆对象?
public static void Main()
{
    var foo = new Foo();
    Bar.Baz(foo);
}

public static class Bar
{
    public static void Baz(Foo foo)
    {
        foo = foo.DeepClone();
        /* ... modifies members in foo ... */
    }
}

public class Foo { /* ... */ }

所以,我的问题是:

  • where 有哪些好的经验法则可以跨语言克隆对象,尤其是在 C# 和 .NET 领域?

  • 无论答案如何,有哪些好的方法可以记录修改参数的方法或克隆对象的方法的行为?

【问题讨论】:

  • 这个问题属于codereview.stackexchange.com
  • 代码审查声明“如果您的问题不是关于特定的代码段,而是关于……的普遍适用的问题”......“一般的最佳实践(也就是说,可以问”此代码是否遵循常见的最佳实践?”,而不是“关于 X 的最佳实践是什么?”)” ...“那么您的问题与本网站无关。”
  • 这不适合当前形式的代码审查。代码是假设的;我们需要 CR 上的真实代码。如果您希望进行代码审查,请提供您希望审查的所有真实代码。

标签: c# clone single-responsibility-principle responsibility


【解决方案1】:

方法的目的是改变对象吗?然后不要在方法内部克隆。你希望副作用发生。通常,方法名称会清楚地表明预期会发生突变(例如UpdateCustomer)。

如果改变其输入的方法不是明确的目的,那么改变是一个实现细节,并且该方法必须确保改变不会泄漏。它可以通过克隆来做到这一点。

方法不应仅将其输入用作临时空间。 Win32 API 中的某些 API 执行的操作非常令人困惑。

【讨论】:

  • 这些都是很好的提示,并且说明清楚。期望突变与否的调用者之间的区别是我缺少的部分。我很好奇执行此操作的 Win32 API。有资源吗?
  • 写答案的时候找不到。我在 Raymond Chens 的博客上读到了它。该 API 已有数十年的历史,我认为它是一个命令行解析 API。它改变了输入字符串缓冲区并在此过程中简单地销毁它。
  • 知道了。是CreateProcess的命令行参数。
  • 谢谢!看到这样的问题很有趣。
  • 如果您对另一个想法感兴趣:通常,您希望保持调用者和被调用者之间的合同(实际上是任何两个模块之间)尽可能干净。突变保证是合同的一部分。如果你强迫开发人员理解复杂的突变行为,这会减慢他们的速度并导致潜在的错误。例如,命令查询分离旨在消除从查询方法中理解突变行为的需要。一般来说,突变越少越好。如果你必须改变,对其他模块隐藏这个事实。
【解决方案2】:

强制(和记录)常量的最佳方法是定义一个只读接口并将您的参数定义为该接口。任何接受接口的东西都是常量,任何接受完整对象的东西都可能改变对象。

如果您采用这种方法,调用者应该在不希望产生副作用的情况下进行克隆,因为我们已允许被调用者通过传递可修改对象来修改对象。

【讨论】:

  • 在 C#(与 F# 等语言相反)这样的语言中,如果没有明确地只读,将所有对象视为随时可能发生变异是否合理?我看到了实现只读接口的价值,但提供这种保证似乎需要很多开销。
猜你喜欢
  • 2011-01-09
  • 2011-02-04
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-21
  • 2015-04-25
相关资源
最近更新 更多