Как я могу получить метод расширения для изменения исходного объекта?
Я хочу иметь возможность писать методы расширения, чтобы я мог сказать:
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;
}
}
}
Ответы
Ответ 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
Если это ссылочный тип, вам придется изменить его содержимое. Если это тип значения, в котором вы проходите, вам не повезло. Само существование методов расширения внедряется для поддержки функциональных парадигм в С#, и эти функциональные парадигмы по своей сути стремятся к неизменности типов, следовательно, неспособность изменить значение, из которого вызывается метод расширения.
Другими словами, хотя вы можете это сделать, возможно, это не соответствует "духу" функционального программирования.