当你设计不可变类时,你更喜欢:
Layer.ColorCorrect ( layer )
或者
layer.ColorCorrect ( )
对我来说,#1 似乎更直观,而不是 #2,它看起来像是修改了引用的对象,因为它是一个实例方法,它还不如改变内部结构,对吧?
当你设计不可变类时,你更喜欢:
Layer.ColorCorrect ( layer )
或者
layer.ColorCorrect ( )
对我来说,#1 似乎更直观,而不是 #2,它看起来像是修改了引用的对象,因为它是一个实例方法,它还不如改变内部结构,对吧?
我更喜欢使用实例方法,但选择名称以反映它不会更改现有实例的事实。例如:
layer.AfterColorCorrection()
或者
layer.WithCorrectedColors()
使用静态方法很快就会变得很烦人。此外,如果您向用户明确表示该类型是不可变的,他们应该很快就掌握了窍门。每个人都会因为没有真正替换目标中的任何东西而被绊倒String.Replace
——但他们不会一直犯同样的错误。有了更好的名字,你应该没问题。
我问了一个有关“添加”到不可变列表的相关问题 - IMO 的最佳解决方案是使用“加号”而不是“添加”;同样,这并不意味着原始值已更改。您可能会发现该问题的其他答案很有用。
我个人的偏好是专注于使类型是不可变的。例如,我将其称为 ImmutableLayer vs. Layer。或者如果由于某种原因 Immutable 不是一个好词来作为名称的前缀,我将在类中添加一个属性,表明它是 Immutable (在两种情况下都添加了属性)。
这有它的起起落落。最重要的是它提供了一个检查不变性的中心位置。只需快速浏览一下类型,您就可以开展业务了。无需学习新的方法名称或约定。该方法的缺点是您无法在某些类型的推理场景中判断该值是不可变的。例如,此代码同样适用于 ImmutableCollection 和普通 List
var col = GetTheCollection();
col.Add(42);
但是我不喜欢更改方法名称以适应不变性。原因是这是一个你必须反复解决的问题。命名事物应该很容易,但有时却非常困难。想一想您曾经想要使其不可变的所有类型。想象一下,必须为这些类型的每个变异方法找到新的名称或约定。这是一项艰巨的任务,您将花费大量时间来教育用户了解这些新约定。
不过,我的梦想是找到一种方法来增加不可变类型的可见性。因为这是真正的问题,不知道类型是不可变的。目前还没有针对所有场景执行此操作的好方法,但我对下一个版本的语言/IDE 抱有希望。
@JaredPar 有最好的答案,IMO,但没有一个答案很好,因为今天没有任何“伟大”的解决方案。我们需要更好的工具,以及与工具一起发展的设计指南,以更好地应对不可变对象日益流行的问题。
@JonSkeet 的答案在几乎所有内容都是可变的 API 上下文中运行良好,但随着不可变对象成为常态(因为所有方法的名称都很糟糕),它就会下降。
“最佳”名称取决于您周围的代码上下文。我认为在“大部分可变”到“大部分不可变”上下文的范围内唯一可行的策略是 Jared 提到的那个,其中工具使给定对象是否不可变变得显而易见,然后每种方法都有“必要性” name (egoAdd) 对接收者对象产生副作用(如果它是可变的)或返回一个新对象(如果它是不可变的)。
(除此之外:遗憾的是,像“StringBuilder”这样的“流利”有效的 API 意味着您不能只查看方法签名来确定接收者对象是否不可变,因为这些示例“返回 this”是流利的,给出相同的签名作为“返回副本”。)
通常你会有类似的东西:
layer = layer.ColorCorrect([required parameters here]);
这将类似于
mystring = mystring.Substring(1, 2);
创建一个新字符串的位置,它是第一个字符串的子字符串。
编写静态方法,传递实例并使其看起来几乎像“C”这样的过程编程,这绝对违反了OOPS原则。同样在第一种方法中,您键入 Layer 两次,这使读者感到模棱两可。
使用静态方法排除继承,不是吗?这似乎是一个非常重要的限制。