2011-03-11 16 views
9

Mam następujące klasy:Przekaż jako odniesienie: Który jest bardziej czytelny/prawda?

public class Person 
{ 
    public String Name { get; set; } 
} 

Mam metodę, która pobiera w Person i String jako parametry:

public void ChangeName(Person p, String name) 
{ 
    p.Name = name; 
} 

Od Person została przyjęta przez odniesienie, należy zmienić Name z następujących przekazana instancja.

Ale czy ta metoda jest bardziej czytelna niż powyższa?

public Person ChangeName(Person p, String name) 
{ 
    p.Name = name; 
    return p; 
} 
+1

Technicznie 'p' nie jest przekazywane przez referencję w żadnym z tych przykładów. – Amber

+0

@Amber Jak to jest? Jestem prawie pewien, że jest całkowicie niepoprawny. –

+3

'p' * zawiera * i * przekazuje * odniesienie, ale nie * przekazane przez referencję * - istnieje wyraźna różnica między tymi dwoma. Przekaż jako odniesienie (deklarując argumenty jako 'ZmieńNazwa (patrz Osoba Personalna, ...)' zezwala na coś takiego jak 'p = foo', aby całkowicie zmienić, na którą Personę wskazywała zmienna dzwoniącego, a nie tylko zawartość aktualnie wskazano na osobę – Amber

Odpowiedz

12

Czy jest bardziej czytelny? Nie. W rzeczywistości możesz robić więcej, szkodzić im dobrze.

Po zwróceniu obiektu Person może to prowadzić do przekonania, że ​​zamiast modyfikować parametr Person, faktycznie tworzy on nową osobę na podstawie litery p, ale z inną nazwą, a ktoś mógłby błędnie założyć, że p nigdy nie jest zmienione.

Tak czy inaczej, jeśli masz metodę, która nie ma wpływu na klasę, to poza nią prawdopodobnie powinna być statyczna. Dzięki temu wiesz na pewno, że nie ma to wpływu na jej klasę. Tylko ta metoda zwraca wartość, jeśli jest potrzebna do zwrócenia wartości.

Więc tutaj jest moja rekomendacja dla tej metody:

public static void ChangeName(Person p, String name) 
{ 
    p.Name = name; 
} 
0

W przypadku opisałeś, powiedziałbym nie. Nie jest do końca jasne, co próbujesz zrobić za pomocą tej metody. Po prostu użyj obiektu i ustaw właściwość. Wstawienie metody do ścieżki wykonania tylko komplikuje zrozumienie i tworzy inną zależność od obiektu Person i jego wartości bazowej.

Jeśli zadajesz pytanie z meta, które wiąże się z pewnym projektem wykraczającym poza kod, który opublikowałeś, to go brakuje.

0

Pierwsza z nich jest lepsza, z tego powodu druga może prowadzić do przekonania, że ​​p jest niezmienne. Ale cała metoda jest bezużyteczna, ponieważ po prostu wywołuje Settera. Dlaczego po prostu nie zadzwonisz bezpośrednio do setera?

1

Nie ma niczego dobrego/złego w obu podejściach. Zależy od tego, czego potrzebuje twój program.

Powrót parametru przekazywanego do metody jest rzadko potrzebny, ponieważ zawsze możliwe jest użycie zmiennej przekazanej jako argument.

Daje to jednak możliwość ostatecznego pominięcia tej implementacji lub przekazania tej implementacji do innej funkcji, która akceptuje delegatów z podobnymi podpisami. Następnie możesz przekazać inne implementacje, które nie zwracają tego samego obiektu Person.

Zrób to tylko wtedy, gdy naprawdę potrzebujesz elastyczności.

1

Proponuję skorzystać z jednej z następujących czynności dla najlepszej czytelności:

public static void ChangeName(Person p, String name) 
{ 
    p.Name = name; 
} 

public static Person WithName(Person p, String name) 
{ 
    return new Person(p) { Name = name };  
} 

Drugi traktuje obiekt Person jako niezmienne i nie zmienia stan obiektu. Funkcja ChangeName jawnie zmienia stan obiektu wejściowego.Uważam, że ważne jest, aby dokonać wyraźnego rozróżnienia między tymi dwoma rodzajami metod. Dobrą zasadą do naśladowania jest to, że metoda nie powinna zmieniać stanu obiektu I zwracać go w tym samym czasie.

0

Uważam, że twoje drugie podejście nie jest bardziej czytelne YAGNI. Ale jeśli go zmienić jak to

public static class PersonExtensions 
{ 
public static Person ChangeName(this Person p, String name) 
{ 
p.Name = name; 
return p; 
} 

będziesz miał extensionmethod dla płynny interfejs a la

new Person().ChangeName("Peter Smith").SendEmail().Subject("Test Mail").Receiver("....) 
1

przede wszystkim p nie jest przekazywane przez referencję w pierwszym przykładzie . Twoja druga metoda sprawia, że ​​wierzymy, że zwraca ona nowe odniesienie, którym nie jest. Więc nie sądzę, że ten drugi jest jaśniejszy niż pierwszy.

0

Here to ostateczne odniesienie do zrozumienia parametrów przekazujących według wartości/odniesienia.

Patrząc na kod, dlaczego nie używasz nieruchomości?

public string Name 
{ 
    set {name = value;} 
    get { return name; } 
} 

EDIT: Auto implemented properties

public string Name 
{ 
    set; 
    get; 
} 
Powiązane problemy