C# 是一个不可变的列表,它重载'+';有道理吗?

C# 是一个不可变的列表,它重载'+';有道理吗?,c#,operator-overloading,immutability,C#,Operator Overloading,Immutability,它当然没有脱离.NET框架的标准实践。当我看到aa+b时,我总是假设会创建新的东西 static void Main(string[] args) { var list = BuildList(ImmutableList<int>.Empty); var sum = (list + 500).Sum(); Console.WriteLine(sum); Console.ReadLine(); } static ImmutableList<int

它当然没有脱离.NET框架的标准实践。当我看到a
a+b
时,我总是假设会创建新的东西

static void Main(string[] args)
{
    var list = BuildList(ImmutableList<int>.Empty);
    var sum = (list + 500).Sum();
    Console.WriteLine(sum);
    Console.ReadLine();
}

static ImmutableList<int> BuildList(ImmutableList<int> list)
{
    if (list.Count < 1000)
    {
        return BuildList(list + list.Count);
    }
    return list;
}
static void Main(字符串[]args)
{
var list=BuildList(ImmutableList.Empty);
var sum=(列表+500).sum();
控制台写入线(总和);
Console.ReadLine();
}
静态ImmutableList构建列表(ImmutableList列表)
{
如果(list.Count<1000)
{
返回BuildList(list+list.Count);
}
退货清单;
}
更新

请参阅Jon Skeet的文章中关于如何做的内容

令人惊讶的反应


我很惊讶看到这么多的答案一致认为这是有道理的。原则上我也同意,但对我来说,阅读冗长的代码要比不习惯简洁的人阅读简洁的代码容易得多。根据我的工作经验,他们似乎占大多数

我个人不建议对任何不应被视为原语的类重载操作符,如
+
。特别是,在我看来,集合永远不应该使操作符过载

当您有一个小的不可变类或结构,其行为类似于“基元”类型时,运算符重载是有意义的。但是,当您开始尝试为其他类执行此操作时,它确实会影响可维护性

我建议进行显式方法调用


阅读完评论后,我的建议是使用
Concat()
(在框架中匹配)。我更喜欢的另一个选项是
Construct()
,ala(尽管cons通常在前面加上前缀),以使用法非常清楚:

var list = BuildList(ImmutableList<int>.Empty);
var list2 = list.Concat(500); 
// Or: var list2 = list.Construct(500);
var list=BuildList(ImmutableList.Empty);
var list2=list.Concat(500);
//或者:var list2=list.Construct(500);

在这个上下文中,
+
是什么意思?对我来说,它似乎真的不清楚(没有阅读代码)
IList+IList
我可以将其视为一个联合运算符或组合列表(保留重复项)或任何数量的其他内容<代码>IList+int
让我很困惑。在我看来,一个名称清晰的方法会产生比操作符更可读的代码,有人会在每次使用重载操作符时查找操作符或注释。没有什么可说的,这应该保持,但人们似乎确实期待它


如果在内部,这样一个列表的结构允许您通过存储对源代码的引用来创建一个连接列表(很有可能,特别是考虑到不变性会消除混淆副作用的风险),那么我会选择它。如果它可能不得不做一个相对昂贵的手术,那么我不会。“CuthAtEnter()”可能会让某人考虑“在这样一个思想适当的时候,我真的需要在这个紧循环中移动这个内存,还是应该考虑一个不同的方法?”< /P> < P>一个不可更改的字符列表:“<代码> +>代码>是有意义的;我们称之为字符串。通过类比,您可以说,任何重载
+
操作符以调用
Concat
操作的内容的不可变列表都是有意义的

顺便说一句,我最近创建了一个与您描述的类似的函数:

public static IEnumerable<T> Append<T>(this IEnumerable<T> list, T item)
{
    foreach (T i in list)
        yield return i;
    yield return item;
}
公共静态IEnumerable追加(此IEnumerable列表,T项)
{
foreach(列表中的ti)
收益率i;
收益回报项目;
}
我决定
Append
将单个元素添加到列表中,而
Concat
将整个列表添加到列表的末尾。

我会这样做

毕竟,字符串是字符列表


是的,如果我看到+我会立即想到concatenate(唯一的其他可能性是向量和,这很少见)。

当然,这基本上是一个la Haskell列表。这没什么问题。这是一个不能以任何方式变异的
结构体,所以本质上它的行为与
int
的行为完全一样。@ChaosPandion:不,它真的没有。它和int一样是不可变的,但在概念上却大不相同。集合在概念上不是一个基本对象。@chaospanion:我不是说你~不能~这样做-只是我觉得它给你的API增加了一些非常不清楚的东西,可能会大大降低代码的可维护性和可理解性。+1。里德的观点符合微软的框架设计准则。@chaospandio:这种方法会得到什么回报?如果您执行
list=newil([{1,2,3});list2=list.Foo(500),列表2将包含什么?您将如何命名此方法?假设此方法向列表中添加了一个元素,您提供给Jon Skeet的帖子的链接是一个很好的资源。我个人可能会投票支持
.Cons()
.Add()
——除了可变性之外,这与
列表上的
.Add()
一样。我在
Cons
Concat
之间徘徊。Cons操作将一个新元素放在列表的顶部;concat操作创建一个新列表,其中包含第一个列表的所有元素,然后是第二个列表的所有元素。它们是根本不同的操作。+1-你知道这是我在想的,但这似乎给人们带来的困惑确实超过了使用它的简洁性。现在我将永远不会在我的个人项目之外使用它,那么我可能会使用它,但我也想在我的工作中使用它。(我对可空可变列表引起的问题感到非常厌烦。)也许我没有感到困惑,因为Python使用
+
进行列表连接,但我记得我第一次看到它时没有感到困惑。什么样的人会被
list+list
弄糊涂呢?因为有些人不会思考。那太完美了。我有我的接口。:)我跑som