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

Edw*_*uay 26 c# generics extension-methods object

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

lines.ForceSpaceGroupsToBeTabs();
Run Code Online (Sandbox Code Playgroud)

代替:

lines = lines.ForceSpaceGroupsToBeTabs();
Run Code Online (Sandbox Code Playgroud)

但是,以下代码当前输出:

....one
........two
Run Code Online (Sandbox Code Playgroud)

代替:

Tone
TTtwo
Run Code Online (Sandbox Code Playgroud)

我需要在以下代码中更改以使其输出:

Tone
TTtwo
Run Code Online (Sandbox Code Playgroud)

(请注意,为了可见性. = 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

dtb*_*dtb 40

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

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");
    }
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 15

您必须更改原始列表的内容 - 只需重新分配参数以使其具有不同的值即可.像这样的东西:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

值得注意的是,这与扩展方法无关.想象一下你刚刚打过电话:

Helpers.ForceSpaceGroupsToBeTabs(lines);
Run Code Online (Sandbox Code Playgroud)

...因为这就是代码被有效翻译成的东西.关于它是一种扩展方法这一事实并没有什么特别之处; 如果你更改代码以便"普通"静态方法可以工作,那么它也可以作为扩展方法.如评论中所述,扩展方法无法做到的一件事是将第一个参数作为ref参数.

(编辑:我知道这是与dtb发布的完全相同的代码,虽然我们是独立到达那里的.无论如何我仍然保留这个答案,因为它不仅仅是代码.)


Dav*_*ton 12

如果它是引用类型,则必须更改它的内容.如果它是你传入的价值类型,那你就不走运了.扩展方法的存在是为了支持C#中的函数范式,而这些函数范例本质上倾向于类型的不变性,因此无法改变调用扩展方法的值.

换句话说,虽然你可以做到,但它可能不符合函数式编程的"精神".

  • 我认为这个答案的第二部分是误导性的.扩展方法的绝大多数用例是接口,它们是引用类型,在这些情况下,对变异没有特殊限制:功能与普通方法相同,即`a.SomeMethod();`不能使`a `引用别的东西,但可以改变它引用的对象. (3认同)