对于华丽的标题感到抱歉 - 如果我能想出一个简洁的标题,我就不用问这个问题了.
假设我有一个不可变的列表类型.它有一个操作Foo(x),它返回一个带有指定参数的新的不可变列表作为最后的额外元素.因此,要建立一个值为"Hello","immutable","world"的字符串列表,您可以编写:
var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");
Run Code Online (Sandbox Code Playgroud)
(这是C#代码,如果您觉得语言很重要,我最感兴趣的是C#建议.这不是一个基本的语言问题,但语言的习语可能很重要.)
重要的是现有的列表不会被改变Foo- 所以empty.Count仍然会返回0.
获得最终结果的另一种(更惯用的)方式是:
var list = new ImmutableList<string>().Foo("Hello")
.Foo("immutable")
.Foo("word");
Run Code Online (Sandbox Code Playgroud)
我的问题是:Foo最好的名字是什么?
编辑3:正如我稍后透露的那样,该类型的名称可能实际上并不存在ImmutableList<T>,这使得该位置清晰.想象一下,它是TestSuite并且它是不可变的,因为它所属的整个框架是不可变的......
(编辑完3)
到目前为止我提出的选项:
Add:常见于.NET,但意味着原始列表的变异Cons:我相信这是函数式语言中的正常名称,但对于没有这些语言经验的人来说毫无意义Plus:我最喜欢的,它并不意味着我的变异.显然,这也用在Haskell中,但期望略有不同(Haskell程序员可能希望它将两个列表一起添加而不是将一个值添加到另一个列表中).With:与其他一些不可变的约定一致,但它与IMO没有完全相同的"附加性".And:不是很具描述性.我用来选择的标准是:
如果我不够清楚,请询问更多细节......
编辑1:这里是我的喜欢推理Plus来Add.考虑以下两行代码:
list.Add(foo); …Run Code Online (Sandbox Code Playgroud) 更新:我感谢所有的评论,这些评论基本上都是一致的反对意见.虽然提出的每一项反对意见都是有效的,但我觉得棺材中的最终指甲是Ani的精明观察,最终,即使是这个想法表面上提供的一个 微不足道的好处 - 消除样板代码 - 也被这个事实所否定.想法本身需要自己的样板代码.
所以,是的,请相信我说:这将是一个坏主意.
而且只是为了有点挽救我的尊严:我可能是出于争吵的缘故而玩弄它,但我从来没有真正把这个想法卖掉 - 只是好奇地听到别人不得不说的话.诚实.
在你将这个问题视为荒谬之前,我请你考虑以下问题:
IEnumerable<T>从继承*IEnumerable,这意味着实现任何类型的IEnumerable<T>通常必须实现两个 IEnumerable<T>.GetEnumerator 和(明确地)IEnumerable.GetEnumerator.这基本上等于样板代码.foreach覆盖任何具有GetEnumerator方法的类型.因此,如果您的类型使用签名定义了一个方法,那么使用它来枚举它是合法的.MoveNextCurrentpublic IEnumerator<T> GetEnumerator()foreachIEnumerable<T>接口 - 例如,基本上所有的LINQ扩展方法.幸运的是,使用C#通过关键字提供的自动迭代器生成,从可以使用的类型foreach转变IEnumerable<T>为简单的类型yield.所以,把这一切放在一起,我有这个疯狂的想法:如果我只是定义我自己的界面,如下所示:
public interface IForEachable<T>
{
IEnumerator<T> GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)
然后每当我定义一个我想要枚举的类型时,我实现这个接口而不是IEnumerable<T>,不需要实现两个GetEnumerator方法(一个显式).例如:
class NaturalNumbers : IForEachable<int>
{
public IEnumerator<int> GetEnumerator()
{
int …Run Code Online (Sandbox Code Playgroud)