2011-01-26 14 views
6

Soy nuevo en los métodos de extensión y explorar lo que pueden hacer.C# Métodos de extensión - devolver llamada objeto

¿Es posible que al objeto que llama se le asigne la salida sin una asignación específica?

Aquí es un ejemplo sencillo de explicar:

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

En los siguientes ejemplos ...

var foo = "Hello World!"; 

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

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

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

... ¿hay alguna manera de conseguir foo.ExtensionTest() a resultar en "Hello World! Extended!" sin asignar específicamente foo = foo.ExtensionTest()

+0

Parece que estás en busca de un 'este modificador ref' en un método estático, donde la llamada in situ se ve como 'foo.Extension();'. Desafortunadamente, el idioma no tiene esta característica en este momento. Tal vez algo para recomendar a los diseñadores de idiomas? :) Personalmente, no lo quisiera. – Ani

+3

@Ani: ¡Jaja, no! Oh hombre, ¿puedes imaginar el * abuso * que seguiría? 'string bar = foo; foo.DoSomething(); Console.WriteLine (ReferenceEquals (bar, foo)); '... (salida:' False', desarrollador: * WHAAAT?!? *) –

+1

@Dan Tao: Exactamente. Todos sus refs pertenecen a métodos estáticos. – Ani

Respuesta

13

No, pero la razón por la que no funcionará tiene que ver con la inmutabilidad de las cadenas y nada que ver con los métodos de extensión.

Si por el contrario usted tenía una clase:

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

Y un método de extensión:

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

tendría el efecto de:

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

Console.WriteLine(someClass.Value); //prints "2" 
+0

De hecho, quiero hacer esto en XmlNodes y XmlDocuments: este fue un ejemplo más simple (¡pensé!) Para la pregunta general. – Shevek

5

Lo que está viendo se debe a que las cadenas son inmutables.

En cualquier caso, tendrá tiene para hacer algún tipo de asignación si desea que el objeto cambie.

+0

De hecho, quiero hacer esto en XmlNodes y XmlDocuments: este fue un ejemplo más simple (¡pensé!) Para la pregunta general. – Shevek

4

El parámetro 'this' se pasa por valor, no por referencia. Entonces, no, no puede modificar la variable en el programa de llamada que tiene un alias 'this' en su método de extensión.

1

Nº cadenas en .NET se inmutable. Todos los métodos String públicos también devuelven una nueva instancia de String.

5

Lo más cerca que se podía llegar a esto (lo cual sería raro) sería aceptar un parámetro out y usar eso como el valor de retorno:

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

Ejemplo:

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

El divertido Lo que sucede es que, si bien más cerca se asemeja a lo que estás preguntando, en realidad es un poco más para escribir.

Para que quede claro: yo No recomendar esta, a menos que sea realmente importante para que usted pueda hacer este tipo de llamada al método. La probabilidad de que otro desarrollador pronuncie "WTF?" al ver que tiene que ser algo así como 100%.

+0

+1 Muy desagradable :) – leppie

+0

¡Me gusta! Es un buen trabajo de acuerdo con la pregunta publicada. buen trabajo +1 – VoodooChild

1

Para asignar el nuevo valor a la variable dentro del método de extensión, se necesitaría una modifyer ref en el parámetro, que el compilador de C# no permite en los métodos de extensión (y sería una mala idea de todos modos). Es mejor dejar en claro que estás cambiando la variable.

0

Utilice StringBuilder más rápido para cadenas mutables y como se indicó en ref or out keyword. StringBuilder es básicamente una lista enlazada mejorada para cadenas.
Las cadenas inmutables fueron una decisión de diseño para permitir un comportamiento cercano al lenguaje C y a muchos otros lenguajes.

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. 

Consulte también:

Cuestiones relacionadas