Frage

Wenn wir einen Wert von einem Verfahren erhalten möchten, können wir entweder Rückgabewert wie folgt verwenden:

public int GetValue(); 

oder:

public void GetValue(out int x);

Das verstehe ich nicht wirklich die Unterschiede zwischen ihnen, und so, ich weiß nicht, was besser ist. Können Sie mir das erklären?

Danke.

War es hilfreich?

Lösung

Rückgabewerte sind fast immer die richtige Wahl, wenn das Verfahren nicht über irgendetwas anderes zurückzukehren. (In der Tat kann ich denke nicht an irgendwelche Fälle, in denen ich würde immer eine void-Methode mit einem out Parameter will, wenn ich die Wahl hätte. C # 7s Deconstruct Methoden zur Sprachgestützte Dekonstruktion fungiert als eine sehr, sehr seltene Ausnahme von dieser Regel.)

Abgesehen von allem anderen, stoppt er den Anrufer aus mit der Variable separat zu deklarieren:

int foo;
GetValue(out foo);

vs

int foo = GetValue();

Out-Werte auch verhindern Methode wie folgt verketten:

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

(In der Tat, das ist eines der Probleme, mit Eigenschaftensetter als auch, und es ist, warum die Erbauer Methoden verwendet, die den Builder zurückzukehren, zum Beispiel myStringBuilder.Append(xxx).Append(yyy).)

Zusätzlich out-Parameter mit Reflexion etwas schwieriger zu bedienen sind und in der Regel härter machen testen. (Mehr Aufwand ist in der Regel setzt in so dass es leicht Rückgabewerte als out-Parameter zu verspotten). Im Grunde gibt es nichts, was ich mir vorstellen kann, dass sie erleichtern ...

Rückgabewerte FTW.

EDIT: Im Hinblick darauf, was los ist ...

Im Grunde genommen, wenn Sie in einem Argument für ein "out" Parameter übergeben, Sie wurde in einer Variablen zu übergeben. (Array-Elemente werden als Variablen zu klassifiziert.) Die Methode, die Sie rufen nicht über ein „neues“ Variable auf dem Stapel für den Parameter - es verwendet Ihre Variable für die Lagerung. Alle Änderungen in den Variablen sind sofort sichtbar. Hier ist ein Beispiel den Unterschied zeigt:

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): ");
    }
}

Ergebnisse:

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

Der Unterschied ist bei dem „post“ Schritt - das heißt, nachdem die lokalen Variablen oder Parameter geändert wurden. Im Test Return, macht dies keinen Unterschied zu dem statischen value variabel. Im OutParameter Test wird die value Variable von der Linie tmp = 10; geändert

Andere Tipps

Was ist besser, hängt von Ihrer persönlichen Situation. Ein der Gründe dafür ist out existiert mehrere Werte aus einem Methodenaufruf zu erleichtern Rückkehr:

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

    return input;
}

So ist man nicht per Definition besser als die andere. Aber in der Regel würden Sie wollen eine einfache Rückkehr verwenden, wenn Sie die oben beschriebene Situation zum Beispiel.

EDIT: Dies ist ein Beispiel einer der Gründe, die zeigen, dass das Schlüsselwort vorhanden ist. Die oben ist in keiner Weise eine bewährte Methode berücksichtigt werden.

Sie sollten generell lieber einen Rückgabewert über einen aus param. Out params ist ein neccissary Übel, wenn Sie selbst das Schreiben von Code finden, die 2 Dinge tun muss. Ein gutes Beispiel dafür ist das Try-Muster (wie Int32.TryParse).

Lassen Sie uns überlegen, was der Anrufer Ihrer beiden Methoden zu tun haben würde. Für das erste Beispiel kann ich dies schreibe ...

int foo = GetValue();

Beachten Sie, dass ich eine Variable deklarieren und über Ihre Methode in einer Zeile zuweisen. Für das zweite Beispiel sieht es so aus ...

int foo;
GetValue(out foo);

Ich bin jetzt gezwungen, meine Variable zu deklarieren vorne und meinen Code schreiben über zwei Zeilen.

Update

Ein guter Ort zu suchen, wenn diese Art von Frage zu stellen ist, die .NET Framework-Design-Richtlinien. Wenn Sie die Buch-Version haben, dann können Sie die Anmerkungen von Anders Hejlsberg und andere zu diesem Thema (Seite 184-185) sehen, aber die Online-Version ist hier ...

http://msdn.microsoft.com/en -US / library / ms182131 (VS.80) aspx

Wenn Sie feststellen, dass Sie zwei Dinge aus einer API zurück sie dann nach oben in einer Struktur Verpackung / Klasse wäre besser als eine aus param.

Es gibt einen Grund, eine out param zu verwenden, die erwähnten nicht bereits: die anrufende Methode ist verpflichtet, sie zu empfangen. Wenn Ihre Methode erzeugt einen Wert, den der Anrufer nicht verwerfen sollte, so dass es eine out den Anrufer zwingt es speziell zu akzeptieren:

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

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

Natürlich kann der Anrufer noch ignoriert den Wert in einem out param, aber Sie haben ihre Aufmerksamkeit darauf gelenkt.

Dies ist eine seltene Notwendigkeit; öfter, sollten Sie eine Ausnahme für ein echtes Problem verwenden oder ein Objekt mit Statusinformationen für eine „FYI“ zurückkehren, aber es könnten Umstände geben, wo dies wichtig ist.

Es ist bevorzugt hauptsächlich

Ich ziehe es zurückkehrt und wenn Sie mehrere Renditen haben, können Sie sie in einem Ergebnis DTO wickeln

public class Result{
  public Person Person {get;set;}
  public int Sum {get;set;}
}

Sie sollten fast immer einen Rückgabewert verwenden. ‚out‘ Parameter erstellen ein wenig Reibung zu einer Menge von APIs, Kompositionalität, etc.

Die bemerkenswerteste Ausnahme, dass in dem Sinne, wenn Sie mehrere Werte (.Net Framework nicht über Tupeln bis 4,0), wie zum Beispiel mit dem TryParse Muster.

zurückkehren wollen

Sie können nur einen Rückgabewert, während Sie mehr out-Parameter haben können.

Sie müssen nur Parameter berücksichtigen heraus in diesen Fällen.

Wenn Sie jedoch mehr als ein Parameter von Ihrer Methode zurückgeben müssen, mögen Sie wahrscheinlich sehen, was man von einem OO-Ansatz ist zurückkehren und prüfen, ob Sie besser sind weg ein Objekt oder eine Struktur mit diesen Parametern zurückkehren . Deshalb bist du wieder auf einen Rückgabewert zurück.

Ich würde es vorziehen, das folgend statt entweder von denen in diesem einfachen Beispiel.

public int Value
{
    get;
    private set;
}

Aber, sie sind alle sehr ähnlich. Normalerweise würde man nur verwenden ‚out‘, wenn sie mehrere Werte zurück von der Methode zu übergeben müssen. Wenn Sie einen Wert in das und aus dem Verfahren gesendet werden soll, würde man ‚ref‘ wählen. Meine Methode ist am besten, wenn Sie nur einen Wert zurückgibt, aber wenn Sie einen Parameter übergeben wollen und Wert zurückbekommen würde man wahrscheinlich Ihre erste Wahl wählen.

Beide haben einen anderen Zweck und das gleiche vom Compiler nicht behandelt. Wenn Ihre Methode einen Wert zurückgeben muss, dann müssen Sie Rückkehr verwenden. Out wird verwendet, wenn Ihre Methode mehrere Werte zurückgeben muss.

Wenn Sie Rückkehr verwenden, dann werden die Daten zuerst auf die Methoden geschrieben stapeln und dann in der aufrufenden Methode ist. Während im Fall heraus, wird es an den anrufenden Methode Stapel direkt geschrieben. Nicht sicher, ob es noch weitere Unterschiede.

Es gibt keinen wirklichen Unterschied, out-Parameter in C # sind mehr als ein Wert zu ermöglichen Methode zurückkehren, das ist alles.

Es gibt jedoch einige kleine Unterschiede, aber nicht von ihnen sind wirklich wichtig:

Parameter wird aus werden Sie erzwingen zwei Linien verwenden wie:

int n;
GetValue(n);

während Rückgabewert verwenden lassen Sie tun es in einer Zeile ein:

int n = GetValue();

Einen weiteren Unterschied (korrekten nur für Werttypen und nur dann, wenn C # inline nicht die Funktion) ist, dass Rückgabewert verwendet wird notwendigerweise eine Kopie des Werts, wenn die Funktion Rückkehr während der Parametern mit OUT wird nicht unbedingt so tun.

Wie schon andere gesagt haben:. Rückgabewert, nicht aus param

Darf ich empfehle Ihnen das Buch „Framework Design Guidelines“ (2. Auflage)? Seiten 184-185 decken die Gründe für params vermieden werden. Das ganze Buch werden Sie in die richtige Richtung lenken auf alle Arten von .NET-Codierung Probleme.

Allied mit Framework Design Guidelines ist die Verwendung des statischen Analysetool, FxCop. Sie finden diese auf der Microsoft-Sites als kostenloser Download. Führen Sie diese auf Ihrem kompilierten Code und sehen, was es sagt. Wenn es beschwert mich über Hunderte von Dingen ... keine Panik! Schauen Sie ruhig und sorgfältig auf das, was er sagt, über jeden einzelnen Fall. Sie nicht überstürzen so schnell wie möglich zu beheben. Lernen Sie aus, was Sie zu sagen. Sie werden auf dem Weg zur Meisterschaft gebracht werden.

Ich denke, eine der wenigen Situationen, in denen es nützlich wäre, wäre, wenn es mit dem nicht verwalteten Speicher zu arbeiten, und Sie wollen es auf der Hand, dass die „zurückgegeben“ Wert sollte manuell entsorgt werden, anstatt erwartet, dass es entsorgt werden auf seinem eigenen.

Darüber hinaus Rückgabewerte sind kompatibel mit asynchronen Design-Paradigmen.

Sie können keine Funktion "async" bezeichnen, wenn sie ref oder out-Parameter verwendet.

Insgesamt Rückgabewerte erlaubt Methode Verkettungs, saubere Syntax (durch die Notwendigkeit für den Anrufer zu beseitigen zusätzliche Variablen zu erklären), und ohne die Notwendigkeit einer wesentliche Änderung in der Zukunft für die asynchrone Design zu ermöglichen.

Mit dem Schlüsselwort out mit dem Rückgabetyp Bool, kann manchmal Code aufblasen reduzieren und die Lesbarkeit erhöhen. (Vor allem, wenn die zusätzlichen Informationen in dem aus param werden oft ignoriert.) Zum Beispiel:

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;
        }
    }
}

out ist nützlicher, wenn Sie versuchen, ein Objekt zurückzugeben, die Sie in der Methode deklarieren.

Beispiel

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;
}

Rückgabewert ist der Normalwert, der durch Ihre Methode zurückgegeben wird.

Dabei gilt als aus Parameter, gut und ref sind zwei Schlüsselworte von C # sie passieren lassen Variablen wie Hinweis .

Der große Unterschied zwischen ref und aus ist ref sollte vor und initialisiert wird aus nicht

Ich vermute, ich werde nicht einen Blick in dieser Frage, aber ich bin ein sehr erfahrenen Programmierer, und ich hoffe, einige des aufgeschlossenen Lesers Aufmerksamkeit zu zahlen.

Ich glaube, dass es objektorientierte Programmiersprachen besser für ihre werte Rückkehr Verfahren (VRPs) zu sein, deterministisch und rein paßt.

‚VRP‘ ist der moderne wissenschaftliche Name für eine Funktion, die als Teil eines Ausdruck genannt wird, und hat einen Rückgabewert, der gedanklich den Anruf bei der Auswertung des Ausdrucks ersetzt. Z.B. in einer Erklärung wie x = 1 + f(y) dient die Funktion f als VRP.

‚deterministisch‘ bedeutet, dass das Ergebnis der Funktion nur auf den Wert seines Parameters abhängt. Wenn Sie es wieder mit den gleichen Parameterwerten nennen, sind Sie sicher, um das gleiche Ergebnis zu erhalten.

‚Pure‘ bedeutet, dass keine Nebenwirkungen: Aufruf der Funktion nichts tut außer , um das Ergebnis zu berechnen. Dies kann so interpretiert werden, nicht wichtig Nebenwirkungen in der Praxis so, wenn der VRP gibt eine Debug-Nachricht, die er jedes Mal aufgerufen wird, zum Beispiel, dass wahrscheinlich ignoriert werden.

Wenn also in C #, Ihre Funktion nicht deterministisch und rein ist, sage ich Ihnen eine void Funktion (in anderen Worten, kein VRP) machen sollte, und jeder Wert sollte es entweder ein zurück zurückgeben muss sein out oder ein ref Parameter.

Zum Beispiel, wenn Sie eine Funktion haben einige Zeilen aus einer Datenbanktabelle zu löschen, und Sie wollen es die Anzahl der Zeilen zurück gelöscht, sollten Sie erklären es so etwas wie folgt aus:

public void DeleteBasketItems(BasketItemCategory category, out int count);

Wenn Sie manchmal diese Funktion aufrufen wollen, aber nicht die count bekommen, können Sie immer eine Überlastung erklären.

Sie möchten wissen, Warum Dieser Stil passt die objektorientierte Programmierung besser. Im Großen und Ganzen passt es in eine Art der Programmierung, die (etwas ungenau) bezeichnet ‚prozeduralen Programmierung‘ sein könnte, und es ist eine prozedurale Programmierstil, die besser die objektorientierte Programmierung passt.

Warum? Das klassische Modell der Objekte ist, dass sie Eigenschaften haben (auch bekannt als Attribute), und Sie abfragen und das Objekt (in erster Linie) durch das Lesen und Aktualisieren diese Eigenschaften manipulieren. Ein prozeduralen Programmierung Stil neigt dazu, es einfacher zu machen, dies zu tun, weil Sie beliebigen Code in zwischen Operationen ausführen können, die erhalten und auf Eigenschaften festlegen.

Der Nachteil der prozeduralen Programmierung ist, dass, weil Sie beliebigen Code überall ausführen können, müssen Sie einige sehr stumpfen und Bug-anfällig Interaktionen über globale Variablen und Nebenwirkungen erhalten.

Also, ganz einfach, ist es gute Praxis zu Signal jemand den Code zu lesen, dass eine Funktion zurückkehrt, indem sie nicht-Wert hat Nebenwirkungen könnte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top