2011-01-26 20 views
6

Jestem nowy w metodach rozszerzeń i odkrywaniu, co mogą zrobić.Metody rozszerzania C# - wywołanie zwrotne obiektu

Czy możliwe jest przypisanie obiektu wywołującego danych wyjściowych bez określonego przypisania?

Oto prosty przykład, aby wyjaśnić:

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

W poniższych przykładach ...

var foo = "Hello World!"; 

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

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

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

... czy jest jakiś sposób, aby uzyskać foo.ExtensionTest() spowodować "Hello World! Extended!" bez specjalnie przypisywania foo = foo.ExtensionTest()

+0

Brzmi jak szukasz w 'tego modyfikatora ref' na statycznej metody gdzie call-site wygląda jak 'foo.Extension();'. Niestety język nie ma tej funkcji w tej chwili. Może coś, co mógłbyś polecić projektantom języka? :) Osobiście nie chciałbym tego. – Ani

+3

@Ani: Haha, nie! Och, człowieku, czy możesz sobie wyobrazić * nadużycie *, które się pojawi? 'string bar = foo; foo.DoSomething(); Console.WriteLine (ReferenceEquals (bar, foo)); '... (wynik:' False', programista: * WHAAAT?!? *) –

+1

@Dan Tao: Dokładnie. Wszystkie twoje referencje należą do metod statycznych. – Ani

Odpowiedz

13

Nie, ale powód, dla którego nie zadziała, ma związek z niezmiennością ciągów i nie ma nic wspólnego z metodami rozszerzenia.

Jeśli zamiast tego miał klasę:

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

i metodę rozszerzenia:

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

byłby efekt:

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

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

Naprawdę chcę to zrobić na XmlNodes i XmlDocuments - był to prostszy (myślałem!) Przykład ogólnego pytania. – Shevek

5

To, co widzisz, wynika z tego, że ciągi są niezmienne.

W każdym przypadku będziesz mieć mieć zlecenie, jeśli chcesz zmienić obiekt.

+0

Rzeczywiście chcę to zrobić na XmlNodes i XmlDocuments - to był prostszy (myślałem!) Przykład ogólnego pytania. – Shevek

4

Parametr "ten" jest przekazywany przez wartość, a nie przez odniesienie. Więc nie, nie możesz modyfikować zmiennej w programie wywołującym, która jest aliasowana przez "to" w twojej metodzie rozszerzenia.

1

nr ciągi w .NET są niezmienny. Wszystkie publiczne metody String również zwracają nową instancję String.

5

Najbliższe można dostać się do tego (co byłoby dziwne) byłoby zaakceptować parametr out i użyć jej jako wartości zwracanej:

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

Przykład:

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

Zabawne Rzecz w tym, że podczas gdy dokładniej przypomina o co pytasz, to w rzeczywistości jest nieco więcej do pisania.

Żeby było jasne: ja nie polecam, chyba że jest to naprawdęważne, aby dokonać tego rodzaju metody połączenia. Prawdopodobieństwo, że inny programista wypowie "WTF?" po obejrzeniu musi to być coś w 100%.

+0

+1 Bardzo wredny :) – leppie

+0

Podoba mi się to! Jest to dobre rozwiązanie zgodnie z opublikowanym pytaniem. dobra robota +1 – VoodooChild

1

Aby przypisać nową wartość do zmiennej wewnątrz metody rozszerzenia, potrzebny jest modyfikator zmiany parametru, który kompilator C# nie zezwala na metody rozszerzeń (i tak i tak byłby to zły pomysł). Lepiej wyjaśnić, że zmieniasz zmienną.

0

Użyj szybszego StringBuilder dla zmiennych łańcuchów i jak wskazano ref or out keyword. StringBuilder to w zasadzie ulepszona lista połączonych łańcuchów.
Ciągi niezmienne były decyzją projektową umożliwiającą bliskie zachowanie w języku C i wielu innych językach.

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. 

Zobacz także:

Powiązane problemy