Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Ausschussvariablen sind Platzhaltervariablen, die im Anwendungscode bewusst nicht verwendet werden. Ausschussvariablen entsprechen nicht zugewiesenen Variablen und besitzen keinen Wert. Ein Verwerfen signalisiert dem Compiler und anderen Entwicklern, die Ihren Code lesen: Sie beabsichtigen, das Ergebnis eines Ausdrucks zu ignorieren. Möglicherweise möchten Sie das Ergebnis eines Ausdrucks, einen oder mehrere Bestandteile eines Tupelausdrucks, einen out
-Parameter für eine Methode oder das Ziel eines Mustervergleichsausdrucks ignorieren.
Ausschussvariablen machen den Zweck Ihres Codes deutlich. Ein Verwerfen gibt an, dass der Code niemals die Variable verwendet. Sie verbessern die Lesbarkeit und Wartbarkeit.
Sie geben an, dass eine Variable verworfen wird, indem Sie ihr den Unterstrich (_
) als Namen zuweisen. Der folgende Methodenaufruf gibt beispielsweise einen Tupel zurück, in dem der erste und der zweite Wert Ausschussvariablen sind.
area
ist eine zuvor deklarierte Variable, die auf die dritte von GetCityInformation
zurückgegebene Komponente festgelegt ist.
(_, _, area) = city.GetCityInformation(cityName);
Sie können mithilfe von Ausschussvariablen nicht verwendete Eingabeparameter eines Lambdaausdrucks angeben. Weitere Informationen finden Sie in den Eingabeparametern eines Lambda-Ausdrucksabschnitts im Artikel zu Lambda-Ausdrücken .
Wenn es sich bei _
um eine gültige Ausschussvariable handelt, wird beim Versuch, ihren Wert abzurufen oder sie in einem Zuweisungsvorgang zu verwenden, der Compilerfehler CS0103, „Der Name ‚_‘ existiert im aktuellen Kontext nicht“, generiert. Dieser Fehler liegt daran, dass _
kein Wert zugewiesen ist und möglicherweise nicht einmal einem Speicherort zugewiesen wird. Wenn es sich um eine tatsächliche Variable handelte, konnten Sie nicht mehr als einen Wert verwerfen, wie im vorherigen Beispiel.
Dekonstruieren von Tupeln und Objekten
Ausschussvariablen sind nützlich, wenn mit Tupeln gearbeitet wird und Ihr Anwendungscode einige Elemente des Tupels verwendet, andere aber ignoriert. Die folgende QueryCityDataForYears
Methode gibt z. B. ein Tupel mit dem Namen einer Stadt, seiner Fläche, einem Jahr, der Bevölkerung der Stadt für dieses Jahr, einem zweiten Jahr und der Einwohnerzahl der Stadt für dieses zweite Jahr zurück. Das Beispiel zeigt die Veränderung der Bevölkerung zwischen diesen beiden Jahren. Von den Daten, die im Tupel verfügbar sind, ist die Fläche der Stadt nicht relevant für uns und außerdem kennen wir den Namen der Stadt und die zwei Datumswerte zur Entwurfszeit. Darum sind wir nur an den zwei Bevölkerungsgwerten interessiert, die im Tupel gespeichert sind und behandeln die restlichen Werte als Ausschuss.
var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);
Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");
static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2)
{
int population1 = 0, population2 = 0;
double area = 0;
if (name == "New York City")
{
area = 468.48;
if (year1 == 1960)
{
population1 = 7781984;
}
if (year2 == 2010)
{
population2 = 8175133;
}
return (name, area, year1, population1, year2, population2);
}
return ("", 0, 0, 0, 0, 0);
}
// The example displays the following output:
// Population change, 1960 to 2010: 393,149
Weitere Informationen zum Dekonstruieren von Tupeln mit Ausschüssen finden Sie unter Deconstructing tuples and other types (Dekonstruieren von Tupeln und anderen Typen).
Mit Deconstruct
der Methode einer Klasse, Struktur oder Schnittstelle können Sie auch einen bestimmten Satz von Daten aus einem Objekt abrufen und deconieren. Sie können Ausschussvariablen verwenden, wenn Sie nur mit einer Teilmenge der dekonstruierten Werte arbeiten möchten. Im folgenden Beispiel wird ein Person
Objekt in vier Zeichenfolgen (die Vor- und Nachnamen, die Stadt und das Bundesland) dekonstruiert, der Nachname und das Bundesland jedoch verworfen.
using System;
namespace Discards
{
public class Person
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public string State { get; set; }
public Person(string fname, string mname, string lname,
string cityName, string stateName)
{
FirstName = fname;
MiddleName = mname;
LastName = lname;
City = cityName;
State = stateName;
}
// Return the first and last name.
public void Deconstruct(out string fname, out string lname)
{
fname = FirstName;
lname = LastName;
}
public void Deconstruct(out string fname, out string mname, out string lname)
{
fname = FirstName;
mname = MiddleName;
lname = LastName;
}
public void Deconstruct(out string fname, out string lname,
out string city, out string state)
{
fname = FirstName;
lname = LastName;
city = City;
state = State;
}
}
class Example
{
public static void Main()
{
var p = new Person("John", "Quincy", "Adams", "Boston", "MA");
// Deconstruct the person object.
var (fName, _, city, _) = p;
Console.WriteLine($"Hello {fName} of {city}!");
// The example displays the following output:
// Hello John of Boston!
}
}
}
Weitere Informationen zum Dekonstruieren von benutzerdefinierten Typen mit Ausschüssen finden Sie unter Deconstructing tuples and other types (Dekonstruieren von Tupeln und anderen Typen).
Musterabgleich mit switch
Das Ausschussmuster kann beim Musterabgleich mit dem Schlüsselwort switch expression verwendet werden. Jeder Ausdruck, einschließlich null
, stimmt immer mit dem Ausschussmuster überein.
Im folgenden Beispiel wird eine ProvidesFormatInfo
Methode definiert, die einen switch
Ausdruck verwendet, um zu bestimmen, ob ein Objekt eine IFormatProvider Implementierung bereitstellt, und testet, ob das Objekt ist null
. Sie verwendet auch das Ausschussmuster, um Nicht-NULL-Objekte eines anderen Typs zu verarbeiten.
object?[] objects = [CultureInfo.CurrentCulture,
CultureInfo.CurrentCulture.DateTimeFormat,
CultureInfo.CurrentCulture.NumberFormat,
new ArgumentException(), null];
foreach (var obj in objects)
ProvidesFormatInfo(obj);
static void ProvidesFormatInfo(object? obj) =>
Console.WriteLine(obj switch
{
IFormatProvider fmt => $"{fmt.GetType()} object",
null => "A null object reference: Its use could result in a NullReferenceException",
_ => "Some object type without format information"
});
// The example displays the following output:
// System.Globalization.CultureInfo object
// System.Globalization.DateTimeFormatInfo object
// System.Globalization.NumberFormatInfo object
// Some object type without format information
// A null object reference: Its use could result in a NullReferenceException
Aufrufe von Methoden mit out
Parametern
Beim Aufrufen der Deconstruct
Methode zum Deconieren eines benutzerdefinierten Typs (einer Instanz einer Klasse, Struktur oder Schnittstelle) können Sie die Werte einzelner out
Argumente verwerfen. Sie können jedoch auch den Wert von out
Argumenten verwerfen, wenn Sie eine beliebige Methode mit einem out
Parameter aufrufen.
Im folgenden Beispiel wird die DateTime.TryParse(String, out DateTime)- Methode aufgerufen, um zu bestimmen, ob die Zeichenfolgendarstellung eines Datums in der aktuellen Kultur gültig ist. Da das Beispiel nur mit der Validierung der Datumszeichenfolge und nicht mit dem Parsen zur Datumsextraktion befasst ist, ist das out
Argument für die Methode ein verworfenes Element.
string[] dateStrings = ["05/01/2018 14:57:32.8", "2018-05-01 14:57:32.8",
"2018-05-01T14:57:32.8375298-04:00", "5/01/2018",
"5/01/2018 14:57:32.80 -07:00",
"1 May 2018 2:57:32.8 PM", "16-05-2018 1:00:32 PM",
"Fri, 15 May 2018 20:10:57 GMT"];
foreach (string dateString in dateStrings)
{
if (DateTime.TryParse(dateString, out _))
Console.WriteLine($"'{dateString}': valid");
else
Console.WriteLine($"'{dateString}': invalid");
}
// The example displays output like the following:
// '05/01/2018 14:57:32.8': valid
// '2018-05-01 14:57:32.8': valid
// '2018-05-01T14:57:32.8375298-04:00': valid
// '5/01/2018': valid
// '5/01/2018 14:57:32.80 -07:00': valid
// '1 May 2018 2:57:32.8 PM': valid
// '16-05-2018 1:00:32 PM': invalid
// 'Fri, 15 May 2018 20:10:57 GMT': invalid
Ein eigenständiger Ausschuss
Sie können einen eigenständigen Ausschuss verwenden, um eine beliebige Variable anzugeben, die Sie ignorieren möchten. Eine typische Verwendung ist, mit einer Zuweisung sicherzustellen, dass ein Argument nicht NULL ist. Im folgenden Code wird mit einer Ausschussvariablen eine Zuweisung erzwungen. Auf der rechten Seite der Zuweisung wird mit dem NULL-Sammeloperator eine System.ArgumentNullException ausgelöst, wenn das Argument null
ist. Der Code benötigt nicht das Ergebnis der Zuordnung, sodass er verworfen wird. Der Ausdruck erzwingt eine NULL-Überprüfung. Die Ausschussvariable verdeutlicht Ihre Absicht: Das Ergebnis der Zuweisung ist nicht erforderlich oder wird nicht verwendet.
public static void Method(string arg)
{
_ = arg ?? throw new ArgumentNullException(paramName: nameof(arg), message: "arg can't be null");
// Do work with arg.
}
Im folgenden Beispiel wird ein eigenständiger Ausschuss verwendet, um das Objekt Task zu ignorieren, das von einem asynchronen Vorgang zurückgegeben wird. Das Zuweisen der Aufgabe hat den Effekt, die Ausnahme zu unterdrücken, die der Vorgang auslöst, kurz bevor er abgeschlossen wird. Es macht Ihre Absicht klar: Sie möchten den Task
verwerfen und Fehler ignorieren, die aus diesem asynchronen Vorgang generiert werden.
private static async Task ExecuteAsyncMethods()
{
Console.WriteLine("About to launch a task...");
_ = Task.Run(() =>
{
var iterations = 0;
for (int ctr = 0; ctr < int.MaxValue; ctr++)
iterations++;
Console.WriteLine("Completed looping operation...");
throw new InvalidOperationException();
});
await Task.Delay(5000);
Console.WriteLine("Exiting after 5 second delay");
}
// The example displays output like the following:
// About to launch a task...
// Completed looping operation...
// Exiting after 5 second delay
Ohne die Aufgabe einem Verwerfen zuzuweisen, generiert der folgende Code eine Compilerwarnung:
private static async Task ExecuteAsyncMethods()
{
Console.WriteLine("About to launch a task...");
// CS4014: Because this call is not awaited, execution of the current method continues before the call is completed.
// Consider applying the 'await' operator to the result of the call.
Task.Run(() =>
{
var iterations = 0;
for (int ctr = 0; ctr < int.MaxValue; ctr++)
iterations++;
Console.WriteLine("Completed looping operation...");
throw new InvalidOperationException();
});
await Task.Delay(5000);
Console.WriteLine("Exiting after 5 second delay");
Hinweis
Wenn Sie eines der beiden vorherigen Beispiele mit einem Debugger ausführen, beendet der Debugger das Programm, wenn die Ausnahme ausgelöst wird. Ohne einen angefügten Debugger wird die Ausnahme in beiden Fällen automatisch ignoriert.
_
ist auch ein gültiger Bezeichner. Wenn sie außerhalb eines unterstützten Kontexts verwendet wird, _
wird sie nicht als Verworfen, sondern als gültige Variable behandelt. Wenn bereits ein Bezeichner mit dem Namen _
im Bereich vorhanden ist, kann die Verwendung von _
als eigenständiger Ausschuss zu Folgendem führen:
- Versehentliche Änderung des Werts der im Bereich befindlichen Variable
_
, indem dieser der Wert eines beabsichtigten Ausschusses zugewiesen wird. Beispiel:private static void ShowValue(int _) { byte[] arr = [0, 0, 1, 2]; _ = BitConverter.ToInt32(arr, 0); Console.WriteLine(_); } // The example displays the following output: // 33619968
- Compilerfehler beim Verstoß gegen die Typsicherheit. Beispiel:
private static bool RoundTrips(int _) { string value = _.ToString(); int newValue = 0; _ = Int32.TryParse(value, out newValue); return _ == newValue; } // The example displays the following compiler error: // error CS0029: Cannot implicitly convert type 'bool' to 'int'