Методы расширения C # - возврат вызывающего объекта - PullRequest
6 голосов
/ 26 января 2011

Я новичок в методах расширения и изучаю, что они могут сделать.

Возможно ли, чтобы вызывающему объекту был назначен выход без специального назначения?

Вот простой пример для объяснения:

public static string ExtensionTest(this string input)
{
    return input + " Extended!";
}

В следующих примерах ...

var foo = "Hello World!";

var foo2 = foo.ExtensionTest(); // foo2 = "Hello World! Extended!"

foo.ExtensionTest(); // foo = "Hello World!"

foo = foo.ExtensionTest(); // foo = "Hello World! Extended!"

... есть ли способ получить foo.ExtensionTest(), чтобы получить "Hello World! Extended!" без специального назначения foo = foo.ExtensionTest()

Ответы [ 7 ]

13 голосов
/ 26 января 2011

Нет, но причина, по которой это не сработает, связана с неизменяемостью строк, а не с методами расширения.

Если вместо этого у вас был класс:

public class SomeClass
{
     public int Value {get; set;}
}

И метод расширения:

public static void DoIt(this SomeClass someClass)
{
    someClass.Value++;
}

Будет иметь эффект:

var someClass = new SomeClass{ Value = 1 };
someClass.DoIt();

Console.WriteLine(someClass.Value); //prints "2"
5 голосов
/ 26 января 2011

Самое близкое к этому (что было бы странно) было бы принять параметр out и использовать его в качестве возвращаемого значения:

public static void ExtensionTest(this string input, out string output)
{
    output = input + " Extended!";
}

Пример:

string foo = "Hello World!";
foo.ExtensionTest(out foo);

Самое смешное в этом то, что, хотя оно более близко напоминает то, о чем вы спрашиваете, на самом деле это немного больше, чем печатать.

Для ясности: я не рекомендую это, если только действительно не важно для вас, чтобы выполнить вызов такого рода. Вероятность того, что другой разработчик произнесет "WTF?" увидев, это должно быть что-то вроде 100%.

5 голосов
/ 26 января 2011

То, что вы видите, происходит из-за того, что строки являются неизменяемыми.

В любом случае, у вас будет возможность выполнить какое-либо назначение, если вы хотите, чтобы объект изменился.

4 голосов
/ 26 января 2011

Параметр 'this' передается по значению, а не по ссылке.Так что нет, вы не можете изменить переменную в вызывающей программе, которая называется псевдонимом this в вашем методе расширения.

1 голос
/ 26 января 2011

Чтобы присвоить новое значение вашей переменной в методе расширения, вам потребуется модификатор ref для параметра, который компилятор C # не разрешает для методов расширения (и в любом случае это будет плохой идеей).Лучше дать понять, что вы меняете переменную.

1 голос
/ 26 января 2011

Нет.Строки в .NET являются неизменяемыми.Все публичные методы String также возвращают новый экземпляр String.

0 голосов
/ 12 декабря 2013

Используйте более быстрый StringBuilder для изменяемых строк и, как указано, ключевое слово ref или out .StringBuilder - это в основном улучшенный связанный список для строк.
Неизменяемые строки были дизайнерским решением, позволяющим вести себя близко к языку C и многим другим языкам.

string str = "foo";

str  += "bar"; // str will be free for garbage collection, 
//creating a new string object.
//Note: not entirely true in later C# versions.

StringBuilder sb = new StringBuild();
sb.Append("foo");
sb.Append("bar"); // appends object references to a linked list.

См. Также:

...