如何获得扩展方法来更改原始对象?
我希望能够编写扩展方法,以便我可以说:
lines.ForceSpaceGroupsToBeTabs();
而不是:
lines = lines.ForceSpaceGroupsToBeTabs();
但是,以下代码当前输出:
....one
........two
而不是:
Tone
TTtwo
我必须在以下代码中更改什么才能使其输出:
Tone
TTtwo
(请注意,为了可见性,. = space, T = \t
):
using System;
using System.Collections.Generic;
namespace TestExtended82343
{
class Program
{
static void Main(string[] args)
{
List<string> lines = new List<string>();
lines.Add("....one");
lines.Add("........two");
lines.ForceSpaceGroupsToBeTabs();
lines.ForEach(l => Console.WriteLine(l));
Console.ReadLine();
}
}
public static class Helpers
{
public static void ForceSpaceGroupsToBeTabs(this List<string> originalLines)
{
string spaceGroup = new String('.', 4);
List<string> lines = new List<string>();
foreach (var originalLine in originalLines)
{
lines.Add(originalLine.Replace(spaceGroup, "T"));
}
originalLines = lines;
}
}
}
I want to be able to write extension methods so that I can say:
lines.ForceSpaceGroupsToBeTabs();
instead of:
lines = lines.ForceSpaceGroupsToBeTabs();
However, the following code currently outputs:
....one
........two
instead of:
Tone
TTtwo
What do I have to change in the following code to make it output:
Tone
TTtwo
(note that for visibility, . = space, T = \t
):
using System;
using System.Collections.Generic;
namespace TestExtended82343
{
class Program
{
static void Main(string[] args)
{
List<string> lines = new List<string>();
lines.Add("....one");
lines.Add("........two");
lines.ForceSpaceGroupsToBeTabs();
lines.ForEach(l => Console.WriteLine(l));
Console.ReadLine();
}
}
public static class Helpers
{
public static void ForceSpaceGroupsToBeTabs(this List<string> originalLines)
{
string spaceGroup = new String('.', 4);
List<string> lines = new List<string>();
foreach (var originalLine in originalLines)
{
lines.Add(originalLine.Replace(spaceGroup, "T"));
}
originalLines = lines;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您必须修改传递给扩展方法的
List
的内容,而不是保存对列表的引用的变量:You have to modify the contents of the
List<string>
passed to the extension method, not the variable that holds the reference to the list:您必须更改原始列表的内容 - 仅重新分配参数以使其具有不同的值是行不通的。像这样的事情:
值得注意的是,这与扩展方法无关。想象一下您刚刚调用:
... 因为这就是代码被有效转换成的内容。它是一个扩展方法,这一事实并没有什么特别之处;如果您更改代码以使“正常”静态方法可以工作,那么它也可以作为扩展方法工作。正如评论中所指出的,使用扩展方法不能做的一件事就是使第一个参数成为
ref
参数。(编辑:我意识到这与 dtb 发布的代码完全相同,尽管我们独立到达那里。无论如何,我保留这个答案,因为它不仅仅是代码。)
You'd have to change the contents of the original list - just reassigning the parameter to have a different value isn't going to do it. Something like this:
It's worth noting that this has nothing to do with extension methods. Imagine you'd just called:
... because that's what the code is effectively translated into. There's nothing special about the fact that it's an extension method; if you change the code so that the "normal" static method will work, then it'll work as an extension method too. As noted in the comments, one thing you can't do with an extension method is make the first parameter a
ref
parameter.(EDIT: I realise this is the exact same code that dtb posted, although we arrived there independently. I'm keeping this answer anyway, as it's got more than code.)
如果它是引用类型,则必须更改其内容。如果您传递的是值类型,那么您就不走运了。扩展方法的存在本身就是为了支持 C# 中的函数式范例,而这些函数式范例从本质上讲,倾向于类型的不变性,因此无法更改调用扩展方法的值。
换句话说,虽然您可以做到这一点,但它可能不符合函数式编程的“精神”。
If it's a reference type, you'd have to change it's contents. If it's a value type you're passing in, you're out of luck. The very existence of extension methods is put into place to support functional paradigms in C#, and those functional paradigms, by their very essence, tend towards immutability of types, hence the inability to change the value off of which the extension method is called.
In other words, while you could do it, it may not be in keeping with the "spirit" of functional programming.