Подтвердить что ты не робот

Как я могу получить метод расширения для изменения исходного объекта?

Я хочу иметь возможность писать методы расширения, чтобы я мог сказать:

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;
        }
    }
}
4b9b3361

Ответ 1

Вам нужно изменить содержимое 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");
    }
}

Ответ 2

Вам придется изменить содержимое исходного списка - просто переназначить параметр для другого значения не будет. Что-то вроде этого:

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

... потому что это то, что код эффективно переводится. Нет ничего особенного в том, что это метод расширения; если вы измените код так, чтобы "обычный" статический метод работал, то он также будет работать как метод расширения. Как отмечено в комментариях, одна вещь, которую вы не можете сделать с помощью метода расширения, - это сделать первый параметр a ref.

(EDIT: Я понимаю, что это тот же самый код, что и dtb, но мы пришли туда независимо. Я все равно сохраняю этот ответ, поскольку он получил больше кода.)

Ответ 3

Если это ссылочный тип, вам придется изменить его содержимое. Если это тип значения, в котором вы проходите, вам не повезло. Само существование методов расширения внедряется для поддержки функциональных парадигм в С#, и эти функциональные парадигмы по своей сути стремятся к неизменности типов, следовательно, неспособность изменить значение, из которого вызывается метод расширения.

Другими словами, хотя вы можете это сделать, возможно, это не соответствует "духу" функционального программирования.