C# List的泛型重载: 这要怎么做呢?
StringBuilder 类允许您以我认为非常直观的方式将方法调用链接到 .Append()、.AppendFormat() 和其他一些方法,如下所示:
StringBuilder sb = new StringBuilder();
sb.Append("first string")
.Append("second string);
另一方面,List 类的 .Add() 方法手,返回 void - 所以链接调用不起作用。在我看来,这和杰恩·科布的不朽名言“毫无意义”。
我承认我对泛型的理解非常基础,但我想重载 .Add() 方法(和其他方法),以便它们返回原始对象,并允许链接。任何和所有的帮助都将得到进一步的萤火虫报价的奖励。
The StringBuilder class allows you, in what I consider to be a very intuitive way, to chain method calls to .Append(), .AppendFormat() and some others like so:
StringBuilder sb = new StringBuilder();
sb.Append("first string")
.Append("second string);
The List class' .Add() method, on the other hand, returns void - so chaining calls doesn't work. This, in my opinion and the immortal words of Jayne Cobb "just don' make no kinda sense".
I admit that my understanding of Generics is very basic, but I would like to overload the .Add() method (and others) so that they return the original object, and allow chaining. Any and all assistance will be rewarded with further Firefly quotes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您想为
Add
方法保留相同的名称,您可以从基类中隐藏该方法:但是,只有当您使用显式键入为 < 的变量来操作列表时,这才有效。 code>MyList(例如,如果您的变量声明为
IList
,则它将不起作用)。所以我认为涉及扩展方法的解决方案更好,即使这意味着更改方法的名称。尽管其他人已经发布了带有扩展方法的解决方案,但这里还有另一个解决方案,它的优点是保留集合的实际类型:
像这样使用它:
If you want to keep the same name for the
Add
method, you could hide the method from the base class:However, this will only work if you're manipulating the list with a variable explicitly typed as
MyList<T>
(i.e. it won't work if your variable is declared asIList<T>
for instance). So I think the solutions involving an extension method are better, even if that means changing the name of the method.Although others have already posted solutions with extension methods, here's another one, that has the advantage of conserving the actual type of the collection:
Use it like that:
使用可以创建扩展方法
EDIT,
我们还可以使该方法在集合参数上通用
EDIT 2:
也许有人会发现这个技巧很有用,可以利用嵌套对象初始值设定项和集合初始值设定项来设置属性并将值添加到现有实例中。
use can create extension method
EDIT
we can also make this method generic over collection parameter
EDIT 2:
Maybe someone will find this trick useful, it is possible to utilize nested object initializer and collection initializer for setting properties and adding values into existing instances.
*
AddItem
、Append
、AppendList
等(参见下面的评论)我的脑海中浮现出同样的想法其他人也独立地:
}
Thomas 是对的:只要
IList
继承ICollection
你应该使用 ICollection。*
AddItem
,Append
,AppendList
, etc. (see comments below)The same idea came to my mind like other guys' too, independently:
}
And Thomas is right: as far as
IList<T>
inheritsICollection<T>
you should use ICollection.关闭扩展方法:
请注意,我们必须使用新名称创建它,就好像实例成员与签名匹配(您已经抱怨的“添加”),那么扩展方法将不会被调用。
总而言之,我建议不要这样做。虽然我自己喜欢链接,但它在 C# 库中很少见,这意味着它不像其他语言那样惯用,在其他语言中它更常见(这没有技术原因,尽管属性工作方式的一些差异在其他一些语言中更鼓励它使用) ,就像事物的常见方式一样)。因此,它所支持的构造在 C# 中并不像其他地方那样熟悉,并且您的代码更有可能被其他开发人员误读。
Have an extension method off:
Note that we have to create it with a new name, as if an instance member matches the signature (the 'Add' you are already complaining about) then the extension method won't be called.
In all though, I'd recommend against this. While I like chaining myself, it's being rare in C# libraries means it's not as idiomatic as it is in other languages where it's more common (no technical reason for this, though some differences in how properties work encourages it a bit more in some other languages, just the way things are in terms of what is common). Because of this, the constructs it enables aren't as familiar in C# as elsewhere, and your code is more likely to be misread by another dev.
您可以使用具有不同名称的扩展方法:
要创建这样的代码:
要保留名称
Add
,但是,您可以使用这样的方法:并创建这样的代码:
它不不过看起来不错。
也许如果我们改变类型我们可以有更好的语法。
给定这个类:
你可以有这个方法:
并使用这样的代码:
You could use an extension method with a different name:
To create code like this:
To retain the name
Add
, however, you can have a method like this:And create code like this:
It doesn't look that good though.
Maybe if we change the type we can have a better syntax.
Given this class:
You can have this method:
And use code like this:
我确信您不会欣赏这个答案,但是 List<>.Add() 以这种方式工作是有充分理由的。它非常快,它需要与数组竞争,因为它是一种低级方法。然而,它太大了,无法被 JIT 优化器内联。它无法优化您需要返回列表引用的返回语句。
在代码中编写 lst.Add(obj) 是免费的,lst 引用在 CPU 寄存器中可用。
返回引用的 Add() 版本使代码速度几乎慢了 5%。对于所提出的扩展方法来说,情况要糟糕得多,因为涉及到整个额外的堆栈帧。
I'm sure you won't appreciate this answer but there's a very good reason that List<>.Add() works this way. It is very fast, it needs to be to be competitive with an array and because it is such a low-level method. It is however just a hair too big to get inlined by the JIT optimizer. It cannot optimize the return statement you'd need to return the list reference.
Writing lst.Add(obj) in your code is for free, the lst reference is available in a CPU register.
A version of Add() that returns the reference makes the code almost 5% slower. It's a lot worse for the proposed extension method, there an entire extra stack frame involved.
我喜欢其他人提到的扩展方法,因为这似乎很好地回答了问题(尽管您必须为其提供与现有 Add() 不同的方法签名)。另外,像这样的调用中的对象返回似乎确实存在一些不一致(我认为这是一个可变性问题,但字符串构建器是可变的不是吗?),所以你提出了一个有趣的问题。
不过,我很好奇,AddRange 方法是否不能作为开箱即用的解决方案?您想要链接命令而不是将所有内容作为数组传递进来,是否有特殊原因?
做这样的事情会达不到你所需要的吗?
I like the extension approach that others have mentioned as that seems to answer the question well (although you would have to give it a different method signature than the existing Add()). Also, it does seem like there's some inconsistency about object returns on calls like this (I thought it was a mutability issue, but the stringbuilder is mutable isn't it?), so you raise an interesting question.
I'm curious, though, if the AddRange method would not work as an out-of-the-box solution? Is there a particular reason you want to chain the commands instead of passing everything in as a an array?
Would do something like this not accomplish what you need?