2009-06-03 14 views
5
Class c = new Class({ Prop = "Initial" }); 

Mam powyższą klasę. Jak utworzyć metodę modyfikacji?Czy wolisz zwrócić zmodyfikowany obiekt, czy nie?

public Class ModifyIt(Class c) 
{ 
    c.Prop = "changed"; 
    return c; 
} 

lub

public void ModifyIt(Class c) 
{ 
    c.Prop = "changed"; 
} 

Wtedy nazywa tak ...

Class c = ModifyIt(c); 
Console.WriteLine(c.Prop); 
// changed 

czy to

ModifyIt(c) 
Console.WriteLine(c.Prop); 
// changed 

Whats preferencji?

+0

Dlaczego przekazujesz "Class x" jako parametr do ModifyIt()? Czy twoja metoda nie może po prostu wziąć instancji Class jako "this"? Biorąc pod uwagę kod, wszystkie pozostałe odpowiedzi dotyczące łańcucha nie zadziałają. Dla mnie pytanie brzmi, czy twoja klasa jest bardziej typu wartościowego, w takim przypadku nie powinieneś modyfikować swoich instancji, a raczej zwrócić nową z wynikiem operacji. – van

Odpowiedz

2

Fajną rzeczą w zrobieniu tego w pierwszy sposób, w którym faktycznie zwracasz przedmiot po zmianie, jest to, że pozwala na łańcuchowanie metod. Oznacza, że ​​można zrobić coś takiego:

c.ModifyIt("hello").MessWithIt("World").ReallyScrewWithIt("!!!"); 

Jeśli ma to sens z konkretnej klasy, w których można przewidzieć konieczność łączenia, a następnie powrócić instancji. Jeśli nie, możesz go unieważnić. Dobrym tego przykładem jest klasa StringBuilder który pozwala zrobić coś takiego:

myStringBuilder.Replace("!", "?").Append("Something").Remove(4,3); 
+0

"Fajną rzeczą w zrobieniu tego po raz drugi [...] jest to, że pozwala na łańcuchowanie metod". Myślę, że masz na myśli pierwszy sposób. Przepraszamy za komentarz, nie można jeszcze edytować. – PatrikAkerstrand

+0

Ups, właśnie edytowałem mój post, dzięki! – BFree

6

Osobiście wolę command-query separation - czyli metody powracający wynik nie powinien być mutatorów i vice versa. Rozumiem argumenty za tłumem return this, czyli łatwość „łańcuchowych” wzywa:

foo.ChangeThis(23).ChangeThat(45).AndAlso(67); 

ale na pewno nie jest tak źle, aby zakodować te przypadki jako

var x=foo; 
x.ChangeThis(23); x.ChangeThat(45); x.AndAlso(67); 

Tymczasem zalety " command-query separation "(w zdecydowanej większości przypadków, choć wprawdzie nie w 100%), jak to omówiono pod tym adresem URL, znoszą ...

3

Wybór zwrotu instancji obiektu zależałby od na temat sytuacji.

Wspólna Sprawa dla oddawania obiektu metodą jest postrzegana w builder pattern, takie jak klasy StringBuilder:

new StringBuilder("Hello").Append(" ").Append("World!").ToString(); 

Ale w ogóle, jeśli takie method chaining nie zostanie wykonane, I zdecydowałby się nie zwracać niczego. Jeśli zwykłym przypadkiem użycia nie jest użycie zwróconego obiektu (i po prostu upuszczenie go), który wydaje się być marnotrawstwem.

0

Po pierwsze, jeśli zmieniasz tylko jedną właściwość, nie posiadałbym w ogóle oddzielnej funkcji modyfikacji; Właśnie zmieniłem właściwość bezpośrednio. Porzuciwszy to, przyjmijmy, że podajesz prosty przykład czegoś bardziej skomplikowanego, z może kilkoma różnymi zmianami w funkcji modyfikacji.

Użyłbym tego, który zwraca obiekt "Klasa". Pozwala połączyć wiele połączeń. Ponownie, zakładam, że jest to prosty przykład systemu, który jest faktycznie bardziej skomplikowany; Załóżmy, że zamiast tego masz MakeModification(), MakeAnotherModification() i MakeAThirdModification().Jeśli zwróci obiekt „klasa”, można uzyskać następujące składniowej finezja:

Class c = new Class(); 
c.MakeModification().MakeAnotherModification().MakeAThirdModification(); 
0

Właściwie wolę drugi styl jako metoda jest mutator, stąd nowa wartość nie należy się spodziewać, aby być zwrócony, zamiast oczekuje się, że rzeczywista wartość zostanie zmodyfikowana. Jednak może być konieczne wskazanie, że ModifyIt akceptuje zmienną ref tylko w celu wskazania, że ​​rzeczywiste c zostanie zmodyfikowane. c tutaj jest przekazywane przez wartość, chociaż jest to typ odniesienia, nadal istnieje różnica między przekazywaniem typów referencyjnych przez wartość i przekazywaniem typów referencji przez ref. Zobacz:

public void ModifyIt(Myclass c) { c = new MyClass(); } 

w powyższym przypadku zmienna c będą przekazywane przez wartość (tj odpis z odniesieniem będą przekazywane i modyfikowane, aby wskazywał na nowo instanitiated obiektu, co z kolei oznacza, że będzie miał dwa obiekty typu MojaKlasa w tym przypadku Oto przykład, aby zilustrować.

Myclass s = new MyClass() { prop = "value" }; ModifyIt(s); Console.WriteLine(s.prob); // this will print "value" 

chociaż MOdifyIT instanitaited się referenct do nowego obiektu, który powinien oznaczać, że prob zostaną zainicjowane na wartość null, to faktycznie nie zrobił” t tworzenie instancji, tworzyło kopię s. w odróżnieniu od ca se, jeżeli s zostało przekazane przez ref.
Mam nadzieję, że to pomoże!

1

Ja osobiście wolałbym zbudować funkcję taką jak ModifyIt i umieścić ją w klasie, którą tworzę, jeśli jest to możliwe. Powód, dla którego mówię, że jest w obu metodach, modyfikuję zmienną wywołującą, ponieważ przekazuję ją przez odniesienie. Oczywiście, nie mogę tego zrobić dla wszystkich funkcji, ale umieszczenie ref w wywołaniu funkcji pomaga wyjaśnić, że przekazuję zmienną przez odniesienie, nie przekazując zmiennej przez wartość. Przykład:

public Class ModifyIt(ref Class c) 

Dlaczego? Ponieważ jestem w stanie zapomnieć, kiedy wrócę i przeczytam kod, że przekazałem wartość przez odniesienie, a następnie bardziej prawdopodobnie zrobię coś "złego" dla kodu.

Powiązane problemy