Frage

Ich erstelle eine Funktion, in der ich ein Objekt übergeben muss, damit es durch die Funktion geändert werden kann. Was ist der Unterschied zwischen:

public void myFunction(ref MyClass someClass)

und

public void myFunction(out MyClass someClass)

Welches soll ich verwenden und warum?

War es hilfreich?

Lösung

ref teilt dem Compiler mit, dass das Objekt vor der Eingabe der Funktion initialisiert wird, während out teilt dem Compiler mit, dass das Objekt in der Funktion initialisiert wird.

Also, während ref ist zwei Bahnen, out ist nur aus.

Andere Tipps

Das ref Modifikator bedeutet::

  1. Der Wert ist bereits festgelegt und
  2. Die Methode kann es lesen und ändern.

Das out Modifikator bedeutet::

  1. Der Wert ist nicht festgelegt und kann nicht von der Methode gelesen werden bis um es ist festgelegt.
  2. Die Methode muss Stellen Sie es vor, bevor Sie zurückkehren.

Nehmen wir an, Dom taucht in Peters Kabine über das Memo über die TPS -Berichte auf.

Wenn Dom ein Ref -Argument wäre, hätte er eine gedruckte Kopie des Memos.

Wenn Dom ein Ausstreit wäre, würde er Peter zu einer neuen Kopie des Memos drucken, die er mitnehmen kann.

Ich werde mich bei einer Erklärung versuchen:

Ich denke, wir verstehen, wie die Werttypen richtig funktionieren? Werttypen sind (int, lang, struktur usw.). Wenn Sie sie in eine Funktion ohne Ref -Befehl senden, kopiert es die Daten. Alles, was Sie mit diesen Daten in der Funktion tun, wirkt sich nur auf die Kopie aus, nicht auf das Original. Der Befehl ref sendet die tatsächlichen Daten und alle Änderungen wirken sich auf die Daten außerhalb der Funktion aus.

OK weiter zum verwirrenden Teil, Referenztypen:

Erstellen wir einen Referenztyp:

List<string> someobject = new List<string>()

Wenn Sie neu sind ein bisschen objekt, zwei Teile werden erstellt:

  1. Der Speicherblock, der Daten für enthält ein bisschen objekt.
  2. Eine Referenz (Zeiger) auf diesen Datenblock.

Jetzt, wenn Sie einsenden ein bisschen objekt in eine Methode ohne Ref kopiert die Hinweis Zeiger, nicht die Daten. Also hast du jetzt das:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

Zwei Referenzen, die auf dasselbe Objekt hinweisen. Wenn Sie eine Eigenschaft ändern ein bisschen objekt Unter Verwendung von Reference2 wirkt sich dieselben Daten aus, auf die durch Referenz1 hingewiesen wurde.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

Wenn Sie Reference2 nullten oder auf neue Daten verweisen, wirkt sich weder Referenz1 noch die Datenreferenz1 auf.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

Was passiert nun, wenn Sie senden? ein bisschen objekt von Ref zu einer Methode? Das tatsächliche Referenz zu ein bisschen objekt wird an die Methode gesendet. Sie haben jetzt nur einen Verweis auf die Daten:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

Aber was bedeutet das? Es wirkt genau das gleiche wie das Senden eines Anobjekts nicht von Ref, außer zwei Hauptsache:

1) Wenn Sie die Referenz innerhalb der Methode nullten, null sie die außerhalb der Methode.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) Sie können nun die Referenz auf einen völlig anderen Datenort verweisen, und die Referenz außerhalb der Funktion verweist nun auf den neuen Datenort.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

Ref ist in und aus.

Du solltest benutzen out Präferenz, wo immer es für Ihre Anforderungen ausreicht.

aus:

In C#kann eine Methode nur einen Wert zurückgeben. Wenn Sie mehr als einen Wert zurückgeben möchten, können Sie das Out -Keyword verwenden. Der Out-Modifikator kehrt als Rückkehr zurück. Die einfachste Antwort ist, dass das Schlüsselwort „out“ verwendet wird, um den Wert aus der Methode zu erhalten.

  1. Sie müssen den Wert in der Aufruffunktion nicht initialisieren.
  2. Sie müssen den Wert in der aufgerufenen Funktion zuweisen, andernfalls meldet der Compiler einen Fehler.

Ref:

Wenn Sie in C#einen Werttyp wie int, float, doppelt usw. als Argument für den Methodeparameter übergeben, wird er nach Wert übergeben. Wenn Sie den Parameterwert ändern, wirkt sich daher kein Argument in der Methodenaufruf aus. Wenn Sie jedoch den Parameter mit dem Schlüsselwort "Ref" markieren, wird es in der tatsächlichen Variablen widerspiegeln.

  1. Sie müssen die Variable initialisieren, bevor Sie die Funktion aufrufen.
  2. Es ist nicht obligatorisch, dem Ref -Parameter in der Methode einen Wert zuzuweisen. Wenn Sie den Wert nicht ändern, was muss er als "Ref" markieren?

Erweiterung des Hundes, Katzenbeispiel. Die zweite Methode mit Ref ändert das vom Anrufer verwiesene Objekt. Daher "Katze" !!!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

Da Sie an einem Referenztyp (einer Klasse) bestehen ref Weil pro Standard nur a Hinweis an das tatsächliche Objekt wird übergeben und ändern daher immer das Objekt hinter der Referenz.

Beispiel:

public void Foo()
{
    MyClass myObject = new MyClass();
    myObject.Name = "Dog";
    Bar(myObject);
    Console.WriteLine(myObject.Name); // Writes "Cat".
}

public void Bar(MyClass someObject)
{
    someObject.Name = "Cat";
}

Sobald Sie in einer Klasse übergeben, müssen Sie nicht verwenden ref Wenn Sie das Objekt in Ihrer Methode ändern möchten.

ref und out Verhalten Sie sich ähnlich, außer nach Unterschieden.

  • ref Die Variable muss vor der Verwendung initialisiert werden. out Variable kann ohne Zuordnung verwendet werden
  • out Der Parameter muss von der Funktion, die sie verwendet, als nicht zugewiesener Wert behandelt werden. Wir können also initialisiert verwenden out Parameter im aufrufenden Code, aber der Wert geht verloren, wenn die Funktion ausgeführt wird.

Für diejenigen, die mit gutem Beispiel lernen (wie ich) hier ist was Anthony Kolesov sagt.

Ich habe einige minimale Beispiele für Ref, Out und andere erstellt, um den Punkt zu veranschaulichen. Ich behandle keine Best Practices, nur Beispiele, um die Unterschiede zu verstehen.

https://gist.github.com/2upmedia/6d98a57b68d849eee7091

"Bäcker"

Das liegt daran, dass der erste Ihre String-Referenz ändert, um auf "Baker" hinzuweisen. Das Ändern der Referenz ist möglich, da Sie sie über das Keyword von Ref bestanden haben (=> eine Referenz auf eine Referenz auf eine Zeichenfolge). Der zweite Anruf erhält eine Kopie des Verweiss auf die Zeichenfolge.

String sieht zunächst etwas Besonderes aus. Die String ist jedoch nur eine Referenzklasse und wenn Sie definieren

string s = "Able";

Dann ist S ein Verweis auf eine Zeichenfolgeklasse, die den Text "fähig" enthält! Eine weitere Zuordnung zur gleichen Variablen über

s = "Baker";

ändert nicht die ursprüngliche Zeichenfolge, erstellt aber nur eine neue Instanz und wir zeigen auf diese Instanz!

Sie können es mit dem folgenden kleinen Codebeispiel versuchen:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);

Was erwartest du? Was Sie erhalten, ist immer noch "fähig", da Sie die Referenz in S auf eine andere Instanz festlegen, während S2 auf die ursprüngliche Instanz verweist.

Bearbeiten: String ist auch unveränderlich, was bedeutet, dass es einfach keine Methode oder Eigenschaft gibt, die eine vorhandene String-Instanz ändert (Sie können versuchen, eine in den Dokumenten zu finden, aber Sie werden keine Flossen haben :-)). Alle String Manipulationsmethoden geben eine neue String -Instanz zurück! (Deshalb erhalten Sie oft eine bessere Leistung, wenn Sie die StringBuilder -Klasse verwenden.)

Ref bedeutet, dass der Wert im Ref -Parameter bereits festgelegt ist, die Methode kann ihn lesen und ändern. Die Verwendung des REF -Schlüsselworts ist das gleiche wie die Aussage, dass der Anrufer für die Initialisierung des Werts des Parameters verantwortlich ist.


aus teilt dem Compiler mit, dass die Initialisierung des Objekts die Verantwortung der Funktion liegt, die Funktion muss dem Out -Parameter zuweisen. Es darf es nicht nicht zuordnen lassen.

Aus: Eine Rückgabeanweisung kann verwendet werden, um nur einen Wert aus einer Funktion zurückzugeben. Mithilfe der Ausgabeparameter können Sie jedoch zwei Werte aus einer Funktion zurückgeben. Ausgabeparameter sind wie Referenzparameter, außer dass sie Daten eher aus der Methode als in sie übertragen.

Das folgende Beispiel zeigt Folgendes:

using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValue(out int x )
      {
         int temp = 5;
         x = temp;
      }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;

         Console.WriteLine("Before method call, value of a : {0}", a);

         /* calling a function to get the value */
         n.getValue(out a);

         Console.WriteLine("After method call, value of a : {0}", a);
         Console.ReadLine();

      }
   }
}

Ref:Ein Referenzparameter ist eine Referenz auf einen Speicherort einer Variablen. Wenn Sie die Parameter durch Referenz übergeben, wird im Gegensatz zu Wertparametern ein neuer Speicherort für diese Parameter nicht erstellt. Die Referenzparameter repräsentieren den gleichen Speicherort wie die tatsächlichen Parameter, die der Methode zur Verfügung gestellt werden.

In C#deklarieren Sie die Referenzparameter mithilfe des Keywords Ref. Das folgende Beispiel zeigt dies:

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* save the value of x */
         x = y;   /* put y into x */
         y = temp; /* put temp into y */
       }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;
         int b = 200;

         Console.WriteLine("Before swap, value of a : {0}", a);
         Console.WriteLine("Before swap, value of b : {0}", b);

         /* calling a function to swap the values */
         n.swap(ref a, ref b);

         Console.WriteLine("After swap, value of a : {0}", a);
         Console.WriteLine("After swap, value of b : {0}", b);

         Console.ReadLine();

      }
   }
}

Ref und Out arbeiten genau wie in Bezug auf Referenzen und passieren Zeiger wie in C ++.

Für Ref muss das Argument deklariert und initialisiert werden.

Für Out muss das Argument deklariert werden, kann aber initialisiert werden oder auch nicht.

        double nbr = 6; // if not initialized we get error
        double dd = doit.square(ref nbr);

        double Half_nbr ; // fine as passed by out, but inside the calling  method you initialize it
        doit.math_routines(nbr, out Half_nbr);

Autorierungszeit:

(1) Wir erstellen die aufrufende Methode Main()

(2) Es erstellt ein Listenobjekt (das ein Referenztyp -Objekt ist) und speichert es in der Variablen myList.

public sealed class Program 
{
    public static Main() 
    {
        List<int> myList = new List<int>();

Während der Laufzeit:

(3) Die Laufzeit verteilt einen Speicher auf Stapel bei #00, breit genug, um eine Adresse zu speichern ( #00 = myList, Da Variablennamen wirklich nur Aliase für Speicherorte sind)

(4) Laufzeit erstellt ein Listenobjekt auf Heap am Speicherort #FF (alle diese Adressen sind beispielsweise Sakes)

(5) Laufzeit würde dann die Startadresse #FF des Objekts unter #00 speichern (oder in Wörtern die Referenz des Listenobjekts im Zeiger speichert myList)

Zurück zur Autorenzeit:

(6) Wir übergeben dann das Listenobjekt als Argument myParamList zur aufgerufenen Methode modifyMyList und weisen Sie ihm ein neues Listenobjekt zu

List<int> myList = new List<int>();

List<int> newList = ModifyMyList(myList)

public List<int> ModifyMyList(List<int> myParamList){
     myParamList = new List<int>();
     return myParamList;
}

Während der Laufzeit:

(7) Die Laufzeit startet die Anrufroutine für die aufgerufene Methode und überprüft als Teil davon die Art der Parameter.

(8) Beim Auffinden des Referenztyps zuordnet er einen Speicher auf Stapel bei #04 zum Aliasing der Parametervariablen zu myParamList.

(9) Es speichert dann auch den Wert #FF darin.

(10) Die Laufzeit erstellt ein Listenobjekt auf Heap am Speicherort #004 und ersetzt #FF in #04 durch diesen Wert (oder das ursprüngliche Listenobjekt und zeigt auf das neue Listenobjekt in dieser Methode).

Die Adresse in #00 wird nicht geändert und behält den Verweis auf #FF (oder das Original myList Zeiger ist nicht gestört).


Das Ref Das Schlüsselwort ist eine Compiler -Anweisung, um die Generierung von Laufzeitcode für (8) und (9) zu überspringen, was bedeutet, dass für Methodenparameter keine Heap -Zuordnung vorliegt. Es wird den ursprünglichen #00 Zeiger verwendet, um das Objekt bei #FF zu betreiben. Wenn der ursprüngliche Zeiger nicht initialisiert wird, wird die Laufzeit eingestellt, in der er sich nicht weiterführen kann, da die Variable nicht initialisiert wird

Das aus Schlüsselwort ist eine Compiler -Anweisung, die so gut wie Ref mit einer leichten Modifikation bei (9) und (10) ist. Der Compiler erwartet, dass das Argument nicht nicht initialisiert wird und (8), (4) und (5) fortgesetzt wird, um ein Objekt auf dem Haufen zu erstellen und seine Startadresse in der Argumentvariablen zu speichern. Es wird kein nicht initialisierter Fehler geworfen und eine vorherige gespeicherte Referenz wird verloren gehen.

Sie sind so ziemlich gleich - der einzige Unterschied besteht darin, dass eine Variable, die Sie als Out -Parameter übergeben, nicht initialisiert werden muss, und die Methode mit dem Ref -Parameter muss sie auf etwas einstellen.

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Die Ref -Parameter sind für Daten geeignet, die möglicherweise geändert werden. Die Ausgabe von Parametern beziehen sich auf Daten, die eine zusätzliche Ausgabe für die Funktion (z. B. int.tryParse) entsprechen, die bereits den Rückgabewert für etwas verwenden.

Im Folgenden habe ich ein Beispiel mit beiden gezeigt Ref und aus. Jetzt werden Sie alle über Ref und Out geklärt.

In unten erwähntem Beispiel, wenn ich kommentiere // myRefoBj = new MyClass {name = "Ref Outsider Calling !!"};Zeile, wird einen Fehler erhalten "Verwendung von nicht zugewiesenen lokalen Variablen 'MyRefoBj'", aber es gibt keinen solchen Fehler in aus.

Wo kann man Ref verwenden: Wenn wir eine Prozedur mit einem In -Parameter aufrufen und der gleiche Parameter wird verwendet, um die Ausgabe dieses Proc zu speichern.

Wo kann man verwenden: Wenn wir eine Prozedur ohne Parameter aufrufen und der gleiche Param wird verwendet, um den Wert von diesem Proc zu zurückzugeben. Beachten Sie auch die Ausgabe

public partial class refAndOutUse : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        myClass myRefObj;
        myRefObj = new myClass { Name = "ref outside called!!  <br/>" };
        myRefFunction(ref myRefObj);
        Response.Write(myRefObj.Name); //ref inside function

        myClass myOutObj;
        myOutFunction(out myOutObj);
        Response.Write(myOutObj.Name); //out inside function
    }

    void myRefFunction(ref myClass refObj)
    {
        refObj.Name = "ref inside function <br/>";
        Response.Write(refObj.Name); //ref inside function
    }
    void myOutFunction(out myClass outObj)
    {
        outObj = new myClass { Name = "out inside function <br/>" }; 
        Response.Write(outObj.Name); //out inside function
    }
}

public class myClass
{
    public string Name { get; set; }
} 
 public static void Main(string[] args)
    {
        //int a=10;
        //change(ref a);
        //Console.WriteLine(a);
        // Console.Read();

        int b;
        change2(out b);
        Console.WriteLine(b);
        Console.Read();
    }
    // static void change(ref int a)
    //{
    //    a = 20;
    //}

     static void change2(out int b)
     {
         b = 20;
     }

Sie können diesen Code überprüfen, und es wird Ihnen beschrieben, dass Sie vollständig unterschieden werden, wenn Sie "Ref" verwenden. Es bedeutet, dass Sie diese int/String bereits initialisieren.

Wenn Sie jedoch "aus" verwenden, funktioniert es unter beiden Bedingungen, wenn Sie diese int/String initialisieren oder nicht, aber Sie müssen diese int/String in dieser Funktion initialisieren

REF: Das Ref -Schlüsselwort wird verwendet, um ein Argument als Referenz zu übergeben. Dies bedeutet, dass der Wert dieses Parameters in der Methode in der Aufrufmethode reflektiert wird. Ein Argument, das mit einem REF -Schlüsselwort übergeben wird, muss in der Aufrufmethode initialisiert werden, bevor es an die aufgerufene Methode übergeben wird.

OUT: Das Out -Schlüsselwort wird auch verwendet, um ein Argument wie Ref -Keyword zu verabschieden, aber das Argument kann übergeben werden, ohne dass es einen Wert zugewiesen hat. Ein Argument, das mit einem Out -Keyword übergeben wird, muss in der aufgerufenen Methode initialisiert werden, bevor es wieder zur Aufrufmethode zurückkehrt.

public class Example
{
 public static void Main() 
 {
 int val1 = 0; //must be initialized 
 int val2; //optional

 Example1(ref val1);
 Console.WriteLine(val1); 

 Example2(out val2);
 Console.WriteLine(val2); 
 }

 static void Example1(ref int value) 
 {
 value = 1;
 }
 static void Example2(out int value) 
 {
 value = 2; 
 }
}

/* Output     1     2     

Ref und Out in Method Overloading

Sowohl Ref als auch Out können nicht gleichzeitig zur Überlastung der Methode verwendet werden. Ref und Out werden jedoch zur Laufzeit unterschiedlich behandelt, aber sie werden zum Kompilieren gleich behandelt (CLR unterscheidet nicht zwischen den beiden, während sie IL für Ref und Out erzeugt haben).

Vom Standpunkt einer Methode, die einen Parameter empfängt, der Unterschied zwischen ref und out ist, dass C# erfordert, dass Methoden an jeden schreiben müssen out Parameter vor der Rückkehr und darf nichts mit einem solchen Parameter tun, außer es als eine Übergabe als eine out Parameter oder Schreiben daran, bis es entweder als bestanden wurde out Parameter zu einer anderen Methode oder direkt geschrieben. Beachten Sie, dass einige andere Sprachen solche Anforderungen nicht auferlegen. eine virtuelle oder Schnittstellenmethode, die in C# mit einem deklariert wird out Der Parameter kann in einer anderen Sprache überschrieben werden, die keine besonderen Beschränkungen für solche Parameter auferlegt.

Aus dem Gesichtspunkt des Anrufers wird C# unter vielen Umständen angenommen, wenn er eine Methode mit einem aufruft out Der Parameter führt dazu, dass die bestandene Variable geschrieben wird, ohne zuerst gelesen zu werden. Diese Annahme ist möglicherweise nicht korrekt, wenn Methoden in anderen Sprachen aufgerufen werden. Zum Beispiel:

struct MyStruct
{
   ...
   myStruct(IDictionary<int, MyStruct> d)
   {
     d.TryGetValue(23, out this);
   }
}

Wenn myDictionary identifiziert an IDictionary<TKey,TValue> Implementierung in einer anderen Sprache als C#, obwohl MyStruct s = new MyStruct(myDictionary); Sieht nach einer Aufgabe aus, es könnte möglicherweise abreisen s unverändert.

Beachten Sie, dass Konstruktoren, die in VB.NET geschrieben wurden, im Gegensatz zu C#keine Annahmen darüber treffen out Parameter und löschen Sie alle Felder bedingungslos. Das seltsame Verhalten, auf das oben angespielt wird, tritt nicht auf, wenn Code vollständig in VB oder vollständig in C# geschrieben wurde, kann jedoch auftreten, wenn Code in C# eine in VB.NET geschriebene Methode aufruft.

Wenn Sie Ihren Parameter als REF übergeben möchten, sollten Sie ihn initialisieren, bevor Sie den Parameter an die Funktion geben. Andernfalls zeigt der Compiler selbst den Fehler an. Aber im Fall des Out -Parameters müssen Sie den Objektparameter nicht initialisieren, bevor Sie ihn an die übertragen haben Methode. Sie können das Objekt in der Aufrufmethode selbst initialisieren.

Sie können nicht nur die Variable eines anderen zu einer anderen Instanz einer Klasse zuweisen, mehrere Werte zurückgeben usw. Verwendung ref oder out Lassen Sie uns jemand anderem wissen, was Sie von ihnen brauchen und was Sie mit der Variablen tun möchten, die er zur Verfügung stellt

  • Du brauche nicht ref oder out Wenn Sie nur Dinge ändern wollen Innerhalb das MyClass Instanz, die im Argument verabschiedet wird someClass.

    • In der aufrufenden Methode wird Änderungen wie angezeigt someClass.Message = "Hello World" Ob du benutzt ref, out oder nichts
    • Schreiben someClass = new MyClass() Innerhalb myFunction(someClass) tauscht das von dem gesehene Objekt aus someClass im Bereich der myFunction Nur Methode. Die aufrufende Methode weiß immer noch das Original MyClass Instanz, die es erstellt und an Ihre Methode übergeben hat
  • Du brauchen ref oder out Wenn Sie vorhaben, das auszutauschen someClass Für ein ganz neues Objekt draußen und möchte, dass die aufrufende Methode Ihre Änderung feststellt

    • Schreiben someClass = new MyClass() Innerhalb myFunction(out someClass) ändert das von der Methode bezeichnete Objekt, das aufgerufen wurde myFunction

Andere Programmierer existieren

Und sie wollen wissen, was Sie mit ihren Daten anfangen. Stellen Sie sich vor, Sie schreiben eine Bibliothek, die von Millionen von Entwicklern verwendet wird. Sie möchten, dass sie wissen, was Sie mit ihren Variablen machen, wenn sie Ihre Methoden nennen

  • Verwendung ref stellt eine Anweisung von "eine Variable übergeben, die einem Wert zugewiesen wird, wenn Sie meine Methode aufrufen. Beachten Sie, dass ich sie möglicherweise im Verlauf meiner Methode für etwas anderes ändern könnte Ich bin fertig"

  • Verwendung out macht eine Erklärung von "Übergeben einer Platzhaltervariablen an meine Methode. Es spielt keine Rolle, ob sie einen Wert hat oder nicht. Der Compiler zwingt mich, sie einem neuen Wert zuzuweisen. Ich garantiert absolut, dass das Objekt von Ihrer Variablen darauf hingewiesen wurde Bevor Sie meine Methode angerufen haben, Wille Sei anders, wenn ich fertig bin

Übrigens, in C#7.2 gibt es eine in Modifikator auch

Und das verhindert, dass die Methode die Verabschiedung für einen anderen Fall ausgetauscht hat. Stellen Sie sich vor, dass dies Millionen von Entwicklern "Ihre ursprüngliche variable Referenz geben, und ich verspreche, Ihre sorgfältig gefertigten Daten nicht gegen etwas anderes auszutauschen". in hat einige Besonderheiten, und in einigen Fällen, beispielsweise wenn eine implizite Umwandlung erforderlich ist, um Ihre kurze kompatibel mit einem zu machen in int Der Compiler wird vorübergehend einen int herstellen, Ihren Kurzfilm vergrößern, es durch Referenz übergeben und fertig werden. Es kann dies tun, weil Sie erklärt haben, dass Sie sich nicht damit anlegen.


Microsoft tat dies mit dem .TryParse Methoden auf den numerischen Typen:

int i = 98234957;
bool success = int.TryParse("123", out i);

Durch das Markieren des Parameters als out Sie erklären hier aktiv "wir sind bestimmt Ich werde Ihren sorgfältig gefertigten Wert von 98234957 für etwas anderes verändern. "

Natürlich müssen sie irgendwie, für Dinge wie das Parsen von Werttypen Bibliothek, die Sie erstellen:

public void PoorlyNamedMethod(out SomeClass x)

Sie können sehen, dass es ein ist out, Und Sie können daher wissen, dass wenn Sie Stunden knirschen, um die perfekte Someklasse zu erstellen:

SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);

Nun, das war Zeitverschwendung, all diese Stunden, um diese perfekte Klasse zu machen. Es wird definitiv weggeworfen und durch armlyNamedMethod ersetzt

Achten Sie darauf, dass der Referenzparameter, der in der Funktion übergeben wird, direkt angewendet wird.

Zum Beispiel,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

Dies wird Hund schreiben, keine Katze. Daher sollten Sie direkt an einem Anobjekt arbeiten.

Ich bin vielleicht nicht so gut darin, aber sicherlich werden Strings (auch wenn sie technisch Referenztypen sind und auf dem Haufen leben) von Wert und nicht von Referenz übergeben?

        string a = "Hello";

        string b = "goodbye";

        b = a; //attempt to make b point to a, won't work.

        a = "testing";

        Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!

Aus diesem Grund benötigen Sie Ref, wenn Sie Änderungen außerhalb des Rahmens der Funktion, die sie erzeugt, existieren möchten. Andernfalls übergeben Sie keine Referenz.

Soweit mir bekannt ist, benötigen Sie nur Ref für Strukturen/Werttypen und Zeichenfolge selbst, da String ein Referenztyp ist, der vorgibt, dass er es ist, aber kein Werttyp ist.

Ich könnte hier allerdings völlig falsch liegen, ich bin neu.

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