Co jest lepsze, wartość zwracana czy parametr out?

Jeśli chcemy uzyskać wartość z metody, możemy użyć wartości zwracanej w następujący sposób:

public int GetValue(); 

Lub:

public void GetValue(out int x);
Nie bardzo rozumiem różnice między nimi, więc nie wiem, który jest lepszy. Możesz mi to wyjaśnić? Dziękuję.
 130
Author: Vimvq1987, 2009-05-01

16 answers

Zwracane wartości są prawie zawsze właściwym wyborem, gdy metoda nie ma nic innego do zwrócenia. (W rzeczywistości, nie mogę wymyślić żadnych przypadków, w których chciałbym kiedykolwiek chcę metodę void z parametrem out, gdybym miał wybór. Metoda Deconstruct W C# 7 dla dekonstrukcji wspieranej przez język działa jako bardzo, bardzo rzadki wyjątek od tej reguły.)

Oprócz czegokolwiek innego, uniemożliwia wywołującemu deklarowanie zmiennej osobno:

int foo;
GetValue(out foo);

Vs

int foo = GetValue();

Out wartości również zapobiegają łańcuchowaniu metod w ten sposób:

Console.WriteLine(GetValue().ToString("g"));

(W rzeczy samej, jest to jeden z problemów z seterami właściwości, i dlatego wzorzec builder używa metod, które zwracają konstruktora, np. myStringBuilder.Append(xxx).Append(yyy).)

Dodatkowo, parametry są nieco trudniejsze w użyciu z odbiciem i zwykle utrudniają testowanie. (Zwykle więcej wysiłku wkłada się w ułatwianie kopiowania wartości zwrotnych niż w parametry wyjściowe). W zasadzie nic nie przychodzi mi do głowy, że ułatwiają ...

Zwraca wartości FTW.

EDIT: jeśli chodzi o to, co się dzieje...

Zasadniczo, gdy przekazujesz argument dla parametru" out", to musisz przekazać zmienną. (Elementy tablicy są również klasyfikowane jako zmienne.) Wywołana metoda nie ma" nowej " zmiennej na stosie dla parametru - używa zmiennej do przechowywania. Wszelkie zmiany w zmiennej są natychmiast widoczne. Oto przykład pokazujący różnicę:

using System;

class Test
{
    static int value;

    static void ShowValue(string description)
    {
        Console.WriteLine(description + value);
    }

    static void Main()
    {
        Console.WriteLine("Return value test...");
        value = 5;
        value = ReturnValue();
        ShowValue("Value after ReturnValue(): ");

        value = 5;
        Console.WriteLine("Out parameter test...");
        OutParameter(out value);
        ShowValue("Value after OutParameter(): ");
    }

    static int ReturnValue()
    {
        ShowValue("ReturnValue (pre): ");
        int tmp = 10;
        ShowValue("ReturnValue (post): ");
        return tmp;
    }

    static void OutParameter(out int tmp)
    {
        ShowValue("OutParameter (pre): ");
        tmp = 10;
        ShowValue("OutParameter (post): ");
    }
}

Wyniki:

Return value test...
ReturnValue (pre): 5
ReturnValue (post): 5
Value after ReturnValue(): 10
Out parameter test...
OutParameter (pre): 5
OutParameter (post): 10
Value after OutParameter(): 10

Różnica jest na etapie "post" - tzn. po zmianie lokalnej zmiennej lub parametru. W teście ReturnValue nie ma to żadnej różnicy w stosunku do statycznej zmiennej value. W teście OutParameter zmienna value jest zmieniana przez linię tmp = 10;

 143
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-12 12:36:15

Ogólnie powinieneś preferować wartość zwracaną niż wartość wyjściową. Out params są neccissary zła, jeśli znajdziesz się pisanie kodu, który musi zrobić 2 rzeczy. Dobrym tego przykładem jest wzorzec Try (taki jak Int32.TryParse).

Zastanówmy się, co musiałby zrobić rozmówca twoich dwóch metod. Na pierwszy przykład mogę to napisać...
int foo = GetValue();

Zauważ, że mogę zadeklarować zmienną i przypisać ją za pomocą Twojej metody w jednym wierszu. Dla drugiego przykładu wygląda to tak to...

int foo;
GetValue(out foo);

Jestem teraz zmuszony zadeklarować swoją zmienną z góry i napisać mój kod w dwóch liniach.

Update

Dobrym miejscem do szukania podczas zadawania tego typu pytań jest. NET Framework Design Guidelines. Jeśli masz wersję książkową to możesz zobaczyć adnotacje Andersa Hejlsberga i innych na ten temat (str. 184-185) ale wersja online jest proszę...

Http://msdn.microsoft.com/en-us/library/ms182131 (VS. 80). aspx

Jeśli uznasz, że potrzebujesz zwrócić dwie rzeczy z API, zawijanie ich do struktury/klasy byłoby lepsze niż out param.

 23
Author: Martin Peck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 09:58:21

Co jest lepsze, zależy od twojej konkretnej sytuacji. jednym z powodów istnienia out jest ułatwienie zwracania wielu wartości z jednego wywołania metody:

public int ReturnMultiple(int input, out int output1, out int output2)
{
    output1 = input + 1;
    output2 = input + 2;

    return input;
}
Więc jeden z nich nie jest z definicji lepszy od drugiego. Ale zazwyczaj chcesz użyć prostego zwrotu, chyba że masz na przykład powyższą sytuację.

EDIT: Jest to przykład pokazujący jeden z powodów, dla których słowo kluczowe istnieje. Powyższe nie jest w żaden sposób uważane za najlepszą praktykę.

 22
Author: pyrocumulus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 10:25:37

Jest jeden powód, aby użyć param out, który nie został jeszcze wymieniony: metoda wywołująca jest zobowiązana do jego otrzymania. Jeśli twoja metoda generuje wartość, której wywołujący nie powinien odrzucić, czyniąc ją out zmusza wywołującego do jej przyjęcia:

 Method1();  // Return values can be discard quite easily, even accidentally

 int  resultCode;
 Method2(out resultCode);  // Out params are a little harder to ignore

Oczywiście rozmówca może nadal ignorować wartość w param out, ale zwróciłeś na to ich uwagę.

Jest to rzadka potrzeba; częściej należy użyć wyjątku dla prawdziwego problemu lub zwraca obiekt z informacją o stanie dla "FYI" , ale mogą być okoliczności, w których jest to ważne.

 9
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-17 15:56:16

To głównie preferencje

Preferuję zwroty i jeśli masz wiele zwrotów, możesz je zawinąć w wynik dto

public class Result{
  public Person Person {get;set;}
  public int Sum {get;set;}
}
 7
Author: Scott Cowan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 09:39:48

Prawie zawsze powinieneś używać wartości zwracanej. Parametry' out ' powodują tarcie na wiele API, kompozycyjność itp.

Najbardziej godnym uwagi wyjątkiem, który przychodzi na myśl, jest to, gdy chcesz zwrócić wiele wartości (. Net Framework ma krotki dopiero w wersji 4.0), na przykład ze wzorem TryParse.

 5
Author: Brian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 15:19:18

Możesz mieć tylko jedną wartość zwracaną, podczas gdy możesz mieć wiele parametrów wyjściowych.

W takich przypadkach wystarczy tylko wziąć pod uwagę parametry.

Jeśli jednak chcesz zwrócić więcej niż jeden parametr ze swojej metody, prawdopodobnie chcesz przyjrzeć się temu, co zwracasz z metody OO i rozważyć, czy lepiej zwrócić obiekt lub strukturę z tymi parametrami. W związku z tym wracasz do wartości zwrotnej.

 4
Author: Robin Day,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 09:50:21

Wolałbym, aby w tym prostym przykładzie, zamiast któregokolwiek z tych.

public int Value
{
    get;
    private set;
}
Ale wszystkie są takie same. Zwykle używa się " out " tylko wtedy, gdy trzeba przekazać wiele wartości z powrotem z metody. Jeśli chcesz wysłać wartość do i z metody, należy wybrać 'ref'. Moja metoda jest najlepsza, jeśli zwracasz tylko wartość, ale jeśli chcesz przekazać parametr i uzyskać wartość z powrotem, prawdopodobnie wybierzesz swój pierwszy wybór.
 2
Author: kenny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 09:38:14

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żywany tam, gdzie metoda musi zwrócić wiele wartości.

Jeżeli stosujesz return, wtedy dane są najpierw zapisywane do stosu metod, a następnie do metod wywołujących. natomiast w przypadku out są bezpośrednio zapisywane do stosu metod wywołujących. Nie wiem, czy są jeszcze jakieś różnice.

 1
Author: danish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 09:49:53

Nie ma rzeczywistej różnicy, parametry są w C#, aby umożliwić metodzie zwrócenie więcej niż jednej wartości, to wszystko.

Są jednak pewne niewielkie różnice, ale żadna z nich nie jest naprawdę ważna:

Użycie parametru out wymusi użycie dwóch linii:

int n;
GetValue(n);

Podczas używania return value pozwoli Ci to zrobić w jednej linii:

int n = GetValue();

Kolejna różnica (poprawna tylko dla typów wartości i tylko jeśli C# nie wstawia funkcji) jest taka, że użycie zwracanej wartości spowoduje koniecznie wykonaj kopię wartości, gdy funkcja powróci podczas używania OUT parametr niekoniecznie to zrobi.

 1
Author: user88637,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 09:50:40

Jak mówili inni: return value, not out param.

Czy Mogę polecić Ci książkę "Framework Design Guidelines" (2nd ed)? Strony 184-185 obejmują powody unikania paramów. Cała książka poprowadzi cię we właściwym kierunku na wszelkiego rodzaju problemy z kodowaniem. NET.

Sprzymierzone z Framework Design Guidelines jest wykorzystanie narzędzia analizy statycznej, FxCop. Znajdziesz to w witrynach Microsoftu do pobrania za darmo. Uruchom to na skompilowanym kodzie i zobacz, co mówi. Jeśli narzeka na setki rzeczy... nie panikuj! Spójrz spokojnie i uważnie na to, co mówi o każdej sprawie. Nie spiesz się, aby naprawić rzeczy jak najszybciej. Ucz się z tego, co ci mówi. Zostaniesz postawiony na drodze do mistrzostwa.

 1
Author: Andrew Webb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 09:59:53

Myślę, że jednym z niewielu scenariuszy, gdzie byłoby to przydatne, byłoby podczas pracy z pamięcią niezarządzaną, i chcesz, aby było oczywiste, że "zwrócona" wartość powinna być usuwana ręcznie, zamiast oczekiwać, że zostanie usunięta sama.

 1
Author: xian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-01 11:01:44

DODATKOWO wartości zwracane są zgodne z paradygmatami asynchronicznego projektowania.

Nie można wyznaczyć funkcji "asynchronicznej", jeśli używa ona parametrów ref lub out.

W podsumowaniu, zwracane wartości pozwalają na łańcuchowanie metod, czystszą składnię (eliminując konieczność deklarowania przez wywołującego dodatkowych zmiennych) i pozwalają na asynchroniczne projekty bez konieczności znaczącej modyfikacji w przyszłości.

 1
Author: firetiger77,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-06 21:04:21

Użycie słowa kluczowego out z zwracanym typem bool, może czasami zmniejszyć nadmuchiwanie kodu i zwiększyć czytelność. (Przede wszystkim, gdy dodatkowe informacje w out param są często ignorowane.) Na przykład:

var result = DoThing();
if (result.Success)
{
    result = DoOtherThing()
    if (result.Success)
    {
        result = DoFinalThing()
        if (result.Success)
        {
            success = true;
        }
    }
}

Vs:

var result;
if (DoThing(out result))
{
    if (DoOtherThing(out result))
    {
        if (DoFinalThing(out result))
        {
            success = true;
        }
    }
}
 1
Author: Paul Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-21 00:52:09

Out jest bardziej użyteczne, gdy próbujesz zwrócić obiekt zadeklarowany w metodzie.

Przykład

public BookList Find(string key)
{
   BookList book; //BookList is a model class
   _books.TryGetValue(key, out book) //_books is a concurrent dictionary
                                     //TryGetValue gets an item with matching key and returns it into book.
   return book;
}
 0
Author: Taera Kwon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-08 05:57:20

Wartość zwracana jest wartością normalną zwracaną przez metodę.

Gdzie jako out parametr, well out i ref są 2 słowami kluczowymi C# pozwalają przekazać zmienne jako reference .

Duża różnica między ref i out jest taka, ref powinny być inicjowane przed i out nie

 0
Author: user2983359,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-30 14:59:59