如何获得扩展方法来更改原始对象?

发布于 2024-08-23 12:20:13 字数 1367 浏览 13 评论 0原文

我希望能够编写扩展方法,以便我可以说:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

有深☉意 2024-08-30 12:20:13

您必须修改传递给扩展方法的 List 的内容,而不是保存对列表的引用的变量:

public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
    string spaceGroup = new String('.', 4);
    for (int i = 0; i < lines.Count; i++)
    {
        lines[i] = lines[i].Replace(spaceGroup, "T");
    }
}

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:

public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
    string spaceGroup = new String('.', 4);
    for (int i = 0; i < lines.Count; i++)
    {
        lines[i] = lines[i].Replace(spaceGroup, "T");
    }
}
筱果果 2024-08-30 12:20:13

您必须更改原始列表的内容 - 仅重新分配参数以使其具有不同的值是行不通的。像这样的事情:

public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
    string spaceGroup = new String('.', 4);
    for (int i = 0; i < lines.Count; i++)
    {
        lines[i] = lines[i].Replace(spaceGroup, "T");
    }
}

值得注意的是,这与扩展方法无关。想象一下您刚刚调用:

Helpers.ForceSpaceGroupsToBeTabs(lines);

... 因为这就是代码被有效转换成的内容。它是一个扩展方法,这一事实并没有什么特别之处;如果您更改代码以使“正常”静态方法可以工作,那么它也可以作为扩展方法工作。正如评论中所指出的,使用扩展方法不能做的一件事就是使第一个参数成为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:

public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
    string spaceGroup = new String('.', 4);
    for (int i = 0; i < lines.Count; i++)
    {
        lines[i] = lines[i].Replace(spaceGroup, "T");
    }
}

It's worth noting that this has nothing to do with extension methods. Imagine you'd just called:

Helpers.ForceSpaceGroupsToBeTabs(lines);

... 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.)

爱已欠费 2024-08-30 12:20:13

如果它是引用类型,则必须更改其内容。如果您传递的是值类型,那么您就不走运了。扩展方法的存在本身就是为了支持 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文