Как я могу заставить дополнительный метод изменять исходный объект?

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

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;
        }
    }
}
26
задан Edward Tanguay 24 February 2010 в 14:45
поделиться

3 ответа

Вы должны изменить содержимое 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");
    }
}
40
ответ дан 28 November 2019 в 06:32
поделиться

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

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, хотя мы прибыли туда независимо. Я все равно сохраняю этот ответ, так как он содержит больше, чем код.)

15
ответ дан 28 November 2019 в 06:32
поделиться

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

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

12
ответ дан 28 November 2019 в 06:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: