6

In einem C# -Programm habe ich eine Methode erstellt, die ein Objekt aus einer Liste löscht. Der Benutzer gibt den Index des zu löschenden Elements ein, der Benutzer wird dann aufgefordert, das Löschen zu bestätigen, und das Element wird aus der Liste entfernt, wenn der Benutzer bestätigt, andernfalls bleibt die Liste gleich.
Ich bin mir nicht sicher über den besten Weg, Argumente an die Methode zu übergeben. Ich habe versucht, die Liste von Referenz vorbei (als out Parameter):In C# sollte ich einen Parameter nach Wert übergeben und die gleiche Variable zurückgeben oder durch Referenz übergeben?

static void DeleteCustomer(out List<Customer> customers) 
{ 
    // ...display list of objects for user to choose from... 
    int deleteId = ReadInt("Enter ID of customer to delete: "); 
    Console.Write("Are you sure you want to delete this customer?"); 
    if (Console.ReadLine().ToLower() == "y") 
    { 
     customers.RemoveAt(deleteId); 
    } 
} 

Der obige Code nicht, wie ich die Fehler Verwendung von nicht zugewiesenen lokalen Variablen ‚Kunden‘ und Die out-Parameter ‚Kunden erhalten funktioniert 'muss zugewiesen werden, bevor die Steuerung die aktuelle Methode verlässt. Ich dachte, ich könnte die Liste nach Wert übergeben und die gleiche Liste zurück, wie folgt aus:

static List<Customer> DeleteCustomer(List<Customer> customers) 
{ 
    int deleteId = ReadInt("Enter ID of customer to delete: "); 
    Console.Write("Are you sure you want to delete this customer?"); 
    if (Console.ReadLine().ToLower() == "y") 
    { 
     customers.RemoveAt(deleteId); 
    } 
    return customers; 
} 

// ...which would be called from another method with: 
List<Customer> customers = DeleteCustomer(customers); 

aber dies scheint nicht effizient wie die gleiche Variable von Wert übergeben wird, und dann zurückgegangen.

Was ist der effizienteste Weg, Argumente in diesem Fall zu übergeben?

+1

Liste wird durch Referenz automatisch übergeben, so dass es nicht zurückgegeben werden muss. Bei der aufrufenden Methode wird die Änderung in der Referenz auf die übergebene Liste angezeigt. – user469104

+2

Siehe: [Parameterübergabe in C# - Von Jon Skeet] (http://www.yoda.arachsys.com/csharp/parameters.html). Versuchen Sie auch die zweite Methode, ohne die Liste zurück zu senden, Sie werden sehen, dass sie geändert wurde. Dies liegt daran, dass die Adresse des Referenztyps als Wert übergeben wird. ** Aber wichtig **, sollten Sie sich jetzt keine Gedanken über Effizienz machen *, schreiben Sie Code, der die Absicht deutlicher vermittelt, und schauen Sie erst später nach verbesserter Leistung. – Habib

+0

Die zweite Methode könnte den Rückgabetyp "void" haben. –

Antwort

4

List wie alle Referenztypen, wird als Referenz an das Objekt übergeben, und keine Kopie davon.

Beachten Sie, dass dies ganz anders aus sagen, es von Referenz übergeben wird, wie die Zuordnung des Parameters implizieren würde propagiert mit dem Anrufer, die es nicht

Es bedeutet, tut das auf die Änderungen Objekt (z. B. die von RemoveAt ausgeführte) wird automatisch an den Aufrufer weitergegeben.

Also, pass einfach auf; keine Notwendigkeit für einen Rückgabewert oder out/ref Parameter.

Sie werden sehr selten out/ref für Referenztypen verwenden, und wenn für Werttypen verwendet, wird der Unterschied in der Leistung so klein sein im Vergleich zu der Rückkehr, dass Sie nicht darum kümmern sollten, wenn Sie profiliert haben und machte sicher dass Das Problem tritt dort auf. Verwenden Sie, was den idiomatischen Sinn macht.

+2

'List wie alle Referenztypen, wird als Verweis auf das Objekt, und keine Kopie davon übergeben. Dies bedeutet, dass Änderungen automatisch an den Aufrufer weitergegeben werden. Das ist nicht richtig. Sie können Ihrem übergebenen Objekt keine Null oder eine neue Instanz zuweisen. Die Adresse des Referenztyps wird als Wert übergeben. – Habib

+1

@Habib Völlig einverstanden. Es ist * als * eine Referenz übergeben; nicht * durch * Referenz. Eine Referenz als Referenz zu übergeben ist anders. Haben Sie eine Formulierung, die für Sie sinnvoller ist? Manchmal wünschte ich mir wirklich, wir hätten Zeiger, es ist so viel einfacher zu erklären ... Ich habe auch bearbeitet (während Sie tippten?), Um die Propagierungsaussage zu klären. – BradleyDotNET

+3

Es ist eine knifflige Aussage, ich bin eher geneigt zu sagen, dass nichts in C# per Referenz weitergegeben wird, wenn ref/out Schlüsselwort verwendet wird. Bei Referenztypen wird Referenz/Adresse als Wert übergeben. – Habib

2

In C# wird der Parameter als Wert übergeben. Dies bedeutet, dass beim Übergeben eines Parameters an eine Methode eine Kopie des Parameters übergeben wird. C# haben Typen nach Wert (wie int) und durch Verweis (wie jede Klasse). C# enthält einen Stapel (wenn Sie alle Varaibles pushen) und einen Heap. Der Wert der Wertetypen drückt direkt in diesen Stapel, während die Referenzen des Referenztyps im Stapel gedrückt werden und der referenzierte Wert im Stapel geschoben wird.
Wenn Sie einen Referenztyp (wie eine Liste) übergeben, wird eine Kopie der Referenz erstellt, diese Kopie verweist jedoch auf dasselbe Objekt in der Liste. Daher wirkt sich jede Änderung direkt auf das Objekt aus, es sei denn, Sie ändern die Referenz (mit einer Zuordnung), aber das ist nicht Ihr Fall.

Dies könnte durch Ihren Code:

static void DeleteCustomer<T>(List<T> customers) 
    { 
     Console.WriteLine("Enter ID of customer to delete: "); 
     int deleteId; 
     if (int.TryParse(Console.ReadLine(), out deleteId)) // if the input is an int 
     { 
      Console.Write("Are you sure you want to delete this customer?"); 
      if (Console.ReadLine().ToLower() == "y") 
      { 
       customers.RemoveAt(deleteId); 
      } 
     } 
     else 
     { 
      Console.WriteLine("This is not valid Id"); 
     } 
    } 

Wenn Sie ein Schlüsselwort out über ref wissen, möchte ich Ihnen auch helfen können, aber für dieses Beispiel ist nicht neccesary.