Jeśli chcemy uzyskać wartość z metody, możemy użyć jednej z wartości zwracanych, na przykład:
public int GetValue();
lub:
public void GetValue(out int x);
Naprawdę nie rozumiem różnic między nimi, więc nie wiem, co jest lepsze. Czy możesz mi to wyjaśnić?
Dziękuję Ci.
Tuple
jeśli chcesz, ale ogólny konsensus jest taki, że jeśli chcesz zwrócić więcej niż jedną rzecz, rzeczy są zwykle w jakiś sposób powiązane i ta relacja jest zwykle najlepiej wyrażona jako klasa.return Tuple.Create(x, y, z);
Czy to nie brzydkie. Poza tym jest już późna pora na wprowadzenie ich na poziomie językowym. Powodem, dla którego nie utworzyłbym klasy zwracającej wartości z parametru ref / out, jest to, że parametry ref / out mają sens tylko w przypadku dużych, zmiennych struktur (takich jak macierze) lub wartości opcjonalnych, a te ostatnie są dyskusyjne.Tuple<>
krotki .NET i C # !. Chciałbym tylko, żeby C # pozwalał na zwracanie anonimowych typów z metod z wnioskiem o typie kompilatora (jakauto
w Dlang).Odpowiedzi:
Zwracane wartości są prawie zawsze właściwym wyborem, gdy metoda nie ma nic innego do zwrócenia. (Właściwie nie przychodzą mi do głowy żadne przypadki, w których kiedykolwiek chciałbym zastosować metodę void z
out
parametrem, gdybym miał wybór.Deconstruct
Metody C # 7 do dekonstrukcji obsługiwanej przez język działają jako bardzo, bardzo rzadki wyjątek od tej reguły .)Oprócz czegokolwiek innego, powstrzymuje wywołującego przed koniecznością oddzielnego deklarowania zmiennej:
vs
Wartości out również zapobiegają tworzeniu łańcuchów metod w następujący sposób:
(Rzeczywiście, jest to również jeden z problemów związanych z ustawianiem właściwości i dlatego wzorzec konstruktora używa metod, które zwracają program budujący, np
myStringBuilder.Append(xxx).Append(yyy)
.)Ponadto nasze parametry są nieco trudniejsze do wykorzystania z odbiciem i zwykle utrudniają testowanie. (Zwykle wkłada się większy wysiłek w ułatwienie mockowania zwracanych wartości niż parametrów wyjściowych). W zasadzie nic nie przychodzi mi do głowy, że ułatwiają ...
Zwracane wartości FTW.
EDYCJA: Jeśli chodzi o to, co się dzieje ...
Zasadniczo kiedy przechodzą argument dla parametru „out”, to mają przekazać w zmiennej. (Elementy tablicy są również klasyfikowane jako zmienne.) Wywołana metoda nie ma „nowej” zmiennej na swoim stosie dla parametru - używa ona Twojej zmiennej do przechowywania. Wszelkie zmiany w zmiennej są natychmiast widoczne. Oto przykład pokazujący różnicę:
Wyniki:
Różnica dotyczy kroku „post” - tj. Po zmianie lokalnej zmiennej lub parametru. W teście ReturnValue nie ma to znaczenia dla
value
zmiennej statycznej . W teście OutParametervalue
zmienna jest zmieniana przez wiersztmp = 10;
źródło
Dictionary.TryGetValue
jest nie tu zastosowanie, jako że nie jest to metoda void. Czy możesz wyjaśnić, dlaczego chcesz miećout
parametr zamiast wartości zwracanej? (Nawet w przypadkuTryGetValue
, wolałbym wartość zwracaną, która zawiera wszystkie informacje wyjściowe, osobiście. Zobacz NodaTime,ParseResult<T>
aby zobaczyć przykład, jak to zaprojektowałem.)out
parametru, nie można po prostu nic zrobić z wartością.Co jest lepsze, zależy od twojej konkretnej sytuacji. Jednym z powodów
out
jest ułatwienie zwracania wielu wartości z jednego wywołania metody:Więc jeden z definicji nie jest lepszy od drugiego. Ale zwykle chcesz użyć prostego zwrotu, chyba że masz na przykład powyższą sytuację.
EDYCJA: To jest przykład przedstawiający jeden z powodów, dla których istnieje słowo kluczowe. Powyższego w żaden sposób nie należy uważać za najlepszą praktykę.
źródło
Generalnie powinieneś preferować wartość zwracaną zamiast parametru out. Nasze parametry są złem koniecznym, jeśli piszesz kod, który musi robić 2 rzeczy. Dobrym przykładem jest wzorzec Try (taki jak Int32.TryParse).
Zastanówmy się, co musiałby zrobić wywołujący z twoich dwóch metod. Dla pierwszego przykładu mogę to napisać ...
Zauważ, że mogę zadeklarować zmienną i przypisać ją za pomocą twojej metody w jednym wierszu. W drugim przykładzie wygląda to tak ...
Jestem teraz zmuszony do zadeklarowania mojej zmiennej z góry i napisania kodu w dwóch wierszach.
aktualizacja
Dobrym miejscem do zadawania tego typu pytań są wytyczne dotyczące projektowania .NET Framework. Jeśli masz wersję książkową, możesz zobaczyć adnotacje Andersa Hejlsberga i innych na ten temat (strony 184-185), ale wersja online jest tutaj ...
http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx
Jeśli okaże się, że musisz zwrócić dwie rzeczy z interfejsu API, zawinięcie ich w strukturę / klasę byłoby lepsze niż parametr wyjściowy.
źródło
Jest jeden powód, aby użyć
out
parametru, o którym jeszcze nie wspomniano: metoda wywołująca musi go odebrać. Jeśli twoja metoda daje wartość, której obiekt wywołujący nie powinien odrzucić, zmuszając goout
do jej akceptacji:Oczywiście rozmówca może nadal ignorować wartości w
out
param, ale pan nazywa swoje uwagi.To rzadka potrzeba; częściej należy użyć wyjątku dla prawdziwego problemu lub zwrócić obiekt z informacją o stanie dla „FYI”, ale mogą zaistnieć okoliczności, w których jest to ważne.
źródło
To głównie preferencje
Wolę zwroty, a jeśli masz wiele zwrotów, możesz je opakować w wynikowe DTO
źródło
Możesz mieć tylko jedną wartość zwracaną, podczas gdy możesz mieć wiele parametrów wyjściowych.
W takich przypadkach wystarczy wziąć pod uwagę parametry.
Jeśli jednak chcesz zwrócić więcej niż jeden parametr ze swojej metody, prawdopodobnie zechcesz przyjrzeć się temu, co zwracasz z podejścia obiektowego i rozważyć, czy lepiej jest zwrócić obiekt lub strukturę z tymi parametrami. Dlatego znowu wracasz do wartości zwracanej.
źródło
Prawie zawsze powinieneś używać wartości zwracanej. '
out
' powodują trochę tarcia w wielu API, kompozycjach itp.Najbardziej godnym uwagi wyjątkiem, który przychodzi na myśl, jest sytuacja, gdy chcesz zwrócić wiele wartości (.Net Framework nie ma krotek do 4.0), na przykład ze
TryParse
wzorcem.źródło
Wolałbym następujące zamiast któregokolwiek z tych w tym prostym przykładzie.
Ale wszystkie są bardzo podobne. Zwykle używa się „out” tylko wtedy, gdy trzeba przekazać wiele wartości z powrotem z metody. Jeśli chcesz wysłać wartość do iz metody, należy wybrać „ref”. Moja metoda jest najlepsza, jeśli zwracasz tylko wartość, ale jeśli chcesz przekazać parametr i odzyskać wartość, prawdopodobnie wybierzesz pierwszy wybór.
źródło
Myślę, że jednym z nielicznych scenariuszy, w których przydałoby się to podczas pracy z pamięcią niezarządzaną, i chcesz, aby było oczywiste, że „zwrócona” wartość powinna zostać usunięta ręcznie, zamiast oczekiwać, że zostanie ona usunięta samodzielnie .
źródło
Ponadto wartości zwracane są zgodne z asynchronicznymi paradygmatami projektowania.
Nie można oznaczyć funkcji „asynchronicznej”, jeśli używa ona parametrów ref lub out.
Podsumowując, wartości zwracane pozwalają na tworzenie łańcuchów metod, czystszą składnię (eliminując konieczność deklarowania przez obiekt wywołujący dodatkowych zmiennych) i pozwalają na asynchroniczne projekty bez konieczności wprowadzania znacznych modyfikacji w przyszłości.
źródło
Oba mają inny cel i nie są traktowane tak samo przez kompilator. Jeśli twoja metoda musi zwrócić wartość, musisz użyć return. Out jest używane, gdy metoda musi zwrócić wiele wartości.
Jeśli używasz return, dane są najpierw zapisywane na stosie metod, a następnie w metodzie wywołującej. W przypadku out, jest on bezpośrednio zapisywany na stosie metod wywołujących. Nie jestem pewien, czy jest więcej różnic.
źródło
Jak powiedzieli inni: zwracana wartość, a nie out param.
Czy mogę polecić książkę „Wytyczne dotyczące projektowania ram” (wyd. 2)? Na stronach 184-185 opisano powody unikania parametrów. Cała książka poprowadzi Cię we właściwym kierunku we wszelkich kwestiach związanych z kodowaniem .NET.
Sprzymierzeńcem z wytycznymi dotyczącymi projektowania ram jest użycie narzędzia do analizy statycznej FxCop. Znajdziesz to w witrynach firmy Microsoft do bezpłatnego pobrania. Uruchom to na skompilowanym kodzie i zobacz, co mówi. Jeśli narzeka na setki rzeczy ... nie panikuj! Spójrz spokojnie i uważnie, co mówi o każdym przypadku. Nie spiesz się, aby naprawić rzeczy jak najszybciej. Dowiedz się, co ci mówi. Zostaniesz skierowany na drogę do mistrzostwa.
źródło
Używanie słowa kluczowego out ze zwracanym typem bool może czasami zmniejszyć rozdęcie kodu i zwiększyć czytelność. (Przede wszystkim, gdy dodatkowe informacje w parametrze out są często ignorowane). Na przykład:
vs:
źródło
Nie ma żadnej różnicy. Parametry wyjściowe są w języku C #, aby umożliwić zwracanie przez metodę więcej niż jednej wartości, to wszystko.
Istnieją jednak drobne różnice, ale żadna z nich nie jest naprawdę ważna:
Użycie parametru out wymusi użycie dwóch linii, takich jak:
natomiast użycie wartości zwracanej pozwoli Ci to zrobić w jednej linii:
Inną różnicą (poprawną tylko dla typów wartości i tylko wtedy, gdy C # nie wbudowuje funkcji) jest to, że użycie wartości zwracanej koniecznie spowoduje utworzenie kopii wartości, gdy funkcja powróci, podczas gdy użycie parametru OUT niekoniecznie będzie to robić.
źródło
out jest bardziej przydatne, gdy próbujesz zwrócić obiekt zadeklarowany w metodzie.
Przykład
źródło
zwracana wartość to normalna wartość zwracana przez Twoją metodę.
Gdzie jako parametr out , well out i ref są 2 słowami kluczowymi języka C #, pozwalają one na przekazywanie zmiennych jako referencji .
Duża różnica między ref i out polega na tym, że ref należy zainicjalizować przed, a out nie
źródło
Podejrzewam, że nie zajrzę do tego pytania, ale jestem bardzo doświadczonym programistą i mam nadzieję, że niektórzy czytelnicy o bardziej otwartych umysłach zwrócą na to uwagę.
Uważam, że lepiej pasuje do języków programowania zorientowanych obiektowo, ponieważ ich procedury zwracania wartości (VRP) są deterministyczne i czyste.
„VRP” to nowoczesna nazwa akademicka funkcji, która jest wywoływana jako część wyrażenia i ma wartość zwracaną, która teoretycznie zastępuje wywołanie podczas oceny wyrażenia. Np. W instrukcji takiej jak
x = 1 + f(y)
funkcjaf
służy jako VRP.„Deterministyczna” oznacza, że wynik funkcji zależy tylko od wartości jej parametrów. Jeśli wywołasz go ponownie z tymi samymi wartościami parametrów, na pewno uzyskasz ten sam wynik.
„Czysty” oznacza brak skutków ubocznych: wywołanie funkcji nie robi nic poza obliczeniem wyniku. W praktyce można to interpretować jako brak istotnych skutków ubocznych, więc jeśli VRP wysyła komunikat debugowania za każdym razem, gdy jest wywoływany, prawdopodobnie można to zignorować.
Tak więc, jeśli w C # twoja funkcja nie jest deterministyczna i czysta, mówię, że powinieneś uczynić ją
void
funkcją (innymi słowy, nie VRP), a każda wartość, którą musi zwrócić, powinna zostać zwrócona w parametrzeout
lubref
parametrze.Na przykład, jeśli masz funkcję usuwania niektórych wierszy z tabeli bazy danych i chcesz, aby zwracała liczbę usuniętych wierszy, powinieneś zadeklarować ją mniej więcej tak:
public void DeleteBasketItems(BasketItemCategory category, out int count);
Jeśli czasami chcesz wywołać tę funkcję, ale nie możesz jej uzyskać
count
, zawsze możesz zadeklarować przeciążenie.Możesz chcieć wiedzieć, dlaczego ten styl lepiej pasuje do programowania obiektowego. Ogólnie rzecz biorąc, pasuje do stylu programowania, który można (trochę nieprecyzyjnie) nazwać „programowaniem proceduralnym” i jest to styl programowania proceduralnego, który lepiej pasuje do programowania obiektowego.
Czemu? Klasyczny model obiektów polega na tym, że mają one właściwości (czyli atrybuty), a Ty odpytujesz i manipulujesz obiektem (głównie) poprzez czytanie i aktualizowanie tych właściwości. Proceduralny styl programowania zwykle ułatwia to, ponieważ między operacjami pobierającymi i ustawiającymi właściwości można wykonać dowolny kod.
Wadą programowania proceduralnego jest to, że ponieważ możesz wykonać dowolny kod w dowolnym miejscu, możesz uzyskać bardzo tępe i podatne na błędy interakcje za pośrednictwem zmiennych globalnych i efektów ubocznych.
Tak więc po prostu dobrą praktyką jest zasygnalizowanie komuś czytającemu kod, że funkcja może mieć skutki uboczne, sprawiając, że nie zwraca wartości.
źródło
_
symbolu odrzucenia, aby zignorować parametr wyjściowy, np .: DeleteBasketItems (category, out _);