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.
Nullable Reference Types ergänzen Referenztypen auf die gleiche Weise, wie Nullwertetypen Werttypen ergänzen. Sie deklarieren eine Variable als NULL-Bezugstyp , indem Sie einen ? an den Typ anfügen. Beispielsweise stellt string? einen Nullwert dar string. Sie können diese neuen Typen verwenden, um Ihre Entwurfsabsicht deutlicher auszudrücken: Einige Variablen müssen immer einen Wert aufweisen , während andere möglicherweise einen Wert fehlen.
In diesem Tutorial erfahren Sie, wie:
- Integrieren Sie Nullable und Nicht-Nullable Referenztypen in Ihre Designs
- Aktivieren von Überprüfungen Ihres Verweistypen, der NULL-Werte zulässt, anhand Ihres Codes.
- Schreiben Sie Code, in dem der Compiler diese Entwurfsentscheidungen erzwingt.
- Verwenden des Verweisfeatures, das NULL-Werte zulässt, in Ihren eigenen Entwürfen.
Voraussetzungen
- Das neueste .NET SDK
- Visual Studio Code-Editor
- Das C# DevKit
In diesem Tutorial wird davon ausgegangen, dass Sie mit C# und .NET vertraut sind (einschließlich Visual Studio oder der .NET-CLI).
Integrieren von Verweistypen, die NULL-Werte zulassen, in Ihre Entwürfe
In diesem Lernprogramm erstellen Sie eine Bibliothek, die das Modellieren einer Umfrage ermöglicht. Der Code verwendet Verweistypen, die NULL-Werte zulassen bzw. nicht zulassen, zur Darstellung der realen Konzepte. Die Fragen der Umfrage können niemals null sein. Ein Befragten möchte eine Frage möglicherweise nicht beantworten. Die Antworten könnten in diesem Fall null lauten.
Der für dieses Beispiel geschriebene Code drückt diese Absicht aus, und der Compiler erzwingt diese Absicht.
Erstellen Sie die Anwendung und aktivieren Sie die nullfähigen Verweistypen
Erstellen Sie eine neue Konsolenanwendung entweder in Visual Studio oder über die Befehlszeile.dotnet new console Benennen Sie die Anwendung NullableIntroduction. Nachdem Sie die Anwendung erstellt haben, müssen Sie festlegen, dass das gesamte Projekt in einem aktivierten nullable Anmerkungskontext kompiliert wird. Öffnen Sie die CSPROJ-Datei, und fügen Sie dem Nullable Element ein PropertyGroup Element hinzu. Legen Sie den Wert der Eigenschaft auf enablefest. Sie müssen sich für das Feature "Nullable Reference Types " in Projekten anmelden, die vor C# 11 / .NET 7 erstellt wurden. Sobald das Feature aktiviert ist, werden vorhandene Referenzvariablendeklarationen zu nicht nullfähigen Verweistypen. Diese Entscheidung hilft zwar beim Auffinden von Problemen, bei denen vorhandener Code möglicherweise keine ordnungsgemäßen NULL-Prüfungen aufweist, aber sie spiegelt möglicherweise nicht genau Ihre ursprüngliche Entwurfsabsicht wider:
<Nullable>enable</Nullable>
Entwerfen der Typen für die Anwendung
Diese Umfrageanwendung erfordert das Erstellen dieser Klassen:
- Eine Klasse, die die Liste der Fragen modelliert.
- Eine Klasse, die eine Liste der Personen modelliert, die für die Umfrage kontaktiert wurden.
- Eine Klasse, die die Antworten einer Person modelliert, die die Umfrage durchgeführt hat.
Diese Typen verwenden sowohl nullable als auch nicht-nullable Referenztypen, um auszudrücken, welche Member erforderlich sind und welche optional sind. Nullfähige Verweistypen zeigen die Entwurfsabsicht klar.
- Die Fragen, die Teil der Umfrage sind, können niemals null sein: Es ist nicht sinnvoll, eine leere Frage zu stellen.
- Die Befragten können niemals null sein. Sie möchten Personen nachverfolgen, die Sie kontaktiert haben, auch die Befragten, die abgelehnt haben, teilzunehmen.
- Eine Antwort auf eine Frage kann null sein. Die Befragten können ablehnen, einige oder alle Fragen zu beantworten.
Sie sind möglicherweise so daran gewöhnt, Referenztypen zu verwenden, die null-Werte zulassen, dass Sie andere Möglichkeiten übersehen, nicht-nullbare Instanzen zu deklarieren.
- Die Auflistung der Fragen sollte keine NULL-Werte zulassen.
- Die Datensammlung der Befragten sollte nicht-nullbar sein.
Beim Schreiben des Codes sehen Sie, dass ein nicht nullabler Verweistyp als Standard für Verweise häufige Fehler vermeidet, die zu NullReferenceExceptions führen könnten. Eine Lektion aus diesem Lernprogramm besteht darin, dass Sie Entscheidungen darüber getroffen haben, welche Variablen möglicherweise oder nicht sein nullkönnten. Die Sprache hat keine Syntax bereitgestellt, um diese Entscheidungen auszudrücken. Jetzt ist dies der Fall.
Die app, die Sie erstellen, führt die folgenden Schritte aus:
- Erstellt eine Umfrage und fügt ihr Fragen hinzu.
- Erstellen eines pseudozufälligen Satzes von Befragten für die Umfrage.
- Kontaktiert die Befragten, bis die Anzahl der abgeschlossenen Umfragen die Zielgröße erreicht.
- Schreibt wichtige Statistiken zu den Umfrageantworten heraus.
Erstellen Sie die Umfrage mit nullfähigen und nicht-nullfähigen Referenztypen
Der erste Code, den Sie schreiben, erstellt die Umfrage. Sie schreiben Klassen, um eine Umfragefrage und eine Umfrageausführung zu modellieren. Ihre Umfrage enthält drei Arten von Fragen, die durch das Format der Antwort unterschieden werden: Ja/Nein Antworten, Zahlenantworten und Textantworten. Erstellen sie eine public SurveyQuestion Klasse:
namespace NullableIntroduction
{
public class SurveyQuestion
{
}
}
Der Compiler interpretiert jede Verweistyp-Variablendeklaration für Code in einem aktivierten Nullable-Anmerkungskontext als Nicht-Nullable-Verweistyp. Sie können Ihre erste Warnung sehen, indem Sie Eigenschaften für den Fragetext und den Fragetyp hinzufügen, wie im folgenden Code gezeigt:
namespace NullableIntroduction
{
public enum QuestionType
{
YesNo,
Number,
Text
}
public class SurveyQuestion
{
public string QuestionText { get; }
public QuestionType TypeOfQuestion { get; }
}
}
Da Sie die Initialisierung QuestionTextnicht ausgeführt haben, gibt der Compiler eine Warnung aus, dass eine nicht nullable Eigenschaft nicht initialisiert wurde. Ihr Design erfordert, dass der Fragetext nicht null ist, daher fügen Sie einen Konstruktor hinzu, um ihn und den QuestionType Wert zu initialisieren. Die fertige Klassendefinition sieht wie der folgende Code aus:
namespace NullableIntroduction;
public enum QuestionType
{
YesNo,
Number,
Text
}
public class SurveyQuestion
{
public string QuestionText { get; }
public QuestionType TypeOfQuestion { get; }
public SurveyQuestion(QuestionType typeOfQuestion, string text) =>
(TypeOfQuestion, QuestionText) = (typeOfQuestion, text);
}
Durch das Hinzufügen des Konstruktors wird die Warnung entfernt. Das Konstruktorargument ist auch ein nicht nullabler Verweistyp, sodass der Compiler keine Warnungen ausstellen kann.
Erstellen Sie als Nächstes eine public Klasse mit dem Namen SurveyRun. Diese Klasse enthält eine Liste von Objekten und Methoden zum Hinzufügen von SurveyQuestion Fragen zur Umfrage, wie im folgenden Code gezeigt:
using System.Collections.Generic;
namespace NullableIntroduction
{
public class SurveyRun
{
private List<SurveyQuestion> surveyQuestions = new List<SurveyQuestion>();
public void AddQuestion(QuestionType type, string question) =>
AddQuestion(new SurveyQuestion(type, question));
public void AddQuestion(SurveyQuestion surveyQuestion) => surveyQuestions.Add(surveyQuestion);
}
}
Wie zuvor müssen Sie das Listenobjekt in einen Wert ohne Null initialisieren, oder der Compiler gibt eine Warnung aus. Es gibt keine Null-Prüfungen in der zweiten Überladung von AddQuestion, da der Compiler dabei hilft, den nicht-nullfähigen Vertrag durchzusetzen: Sie haben diese Variable als nicht-nullfähig deklariert. Während der Compiler vor potenziellen Nullzuweisungen warnt, sind Laufzeit-NULL-Werte weiterhin möglich. Für öffentliche APIs sollten Sie die Argumentüberprüfung auch für nicht nullwerte Referenztypen hinzufügen, da Clientcode möglicherweise keine nullfähigen Verweistypen aktiviert oder absichtlich Null übergeben kann.
Wechseln Sie in Ihrem Editor zu Program.cs , und ersetzen Sie den Inhalt Main durch die folgenden Codezeilen:
var surveyRun = new SurveyRun();
surveyRun.AddQuestion(QuestionType.YesNo, "Has your code ever thrown a NullReferenceException?");
surveyRun.AddQuestion(new SurveyQuestion(QuestionType.Number, "How many times (to the nearest 100) has that happened?"));
surveyRun.AddQuestion(QuestionType.Text, "What is your favorite color?");
Da sich das gesamte Projekt in einem aktivierten Null-Anmerkungskontext befindet, erhalten Sie Warnungen, wenn Sie null an eine beliebige Methode übergeben, die einen nicht-nullablen Verweistyp erwartet. Versuchen Sie es, indem Sie die folgende Zeile hinzufügen zu Main:
surveyRun.AddQuestion(QuestionType.Text, default);
Erstellen von Befragten und Erhalten von Antworten auf die Umfrage
Schreiben Sie als Nächstes den Code, der Antworten auf die Umfrage generiert. Dieser Vorgang umfasst mehrere kleine Aufgaben:
- Erstellen Sie eine Methode, die respondent-Objekte generiert. Diese Objekte stellen Personen dar, die aufgefordert werden, die Umfrage auszufüllen.
- Entwickeln Sie eine Logik, um das Stellen der Fragen an Befragte zu simulieren und Antworten zu sammeln oder zu vermerken, dass ein Befragter nicht geantwortet hat.
- Wiederholen Sie diesen Vorgang, bis genügend Befragten die Umfrage beantworten.
Sie benötigen eine Klasse, um eine Umfrageantwort darzustellen. Fügen Sie sie jetzt hinzu. Aktivieren Sie Nullable-Unterstützung. Fügen Sie eine Id Eigenschaft und einen Konstruktor hinzu, der sie initialisiert, wie im folgenden Code dargestellt:
namespace NullableIntroduction
{
public class SurveyResponse
{
public int Id { get; }
public SurveyResponse(int id) => Id = id;
}
}
Fügen Sie als Nächstes eine static Methode hinzu, um neue Teilnehmer zu erstellen, indem Sie eine zufällige ID generieren:
private static readonly Random randomGenerator = new Random();
public static SurveyResponse GetRandomId() => new SurveyResponse(randomGenerator.Next());
Die Hauptverantwortung dieser Klasse besteht darin, die Antworten für einen Teilnehmer an die Fragen in der Umfrage zu generieren. Diese Verantwortung hat einige Schritte:
- Bitten Sie um Teilnahme an der Umfrage. Wenn die Person nicht zustimmt, geben Sie eine fehlende (oder NULL)-Antwort zurück.
- Stellen Sie jede Frage, und notieren Sie die Antwort. Jede Antwort könnte auch fehlen (oder auf Null gesetzt sein).
Fügen Sie der SurveyResponse-Klasse den folgenden Code hinzu:
private Dictionary<int, string>? surveyResponses;
public bool AnswerSurvey(IEnumerable<SurveyQuestion> questions)
{
if (ConsentToSurvey())
{
surveyResponses = new Dictionary<int, string>();
int index = 0;
foreach (var question in questions)
{
var answer = GenerateAnswer(question);
if (answer != null)
{
surveyResponses.Add(index, answer);
}
index++;
}
}
return surveyResponses != null;
}
private bool ConsentToSurvey() => randomGenerator.Next(0, 2) == 1;
private string? GenerateAnswer(SurveyQuestion question)
{
switch (question.TypeOfQuestion)
{
case QuestionType.YesNo:
int n = randomGenerator.Next(-1, 2);
return (n == -1) ? default : (n == 0) ? "No" : "Yes";
case QuestionType.Number:
n = randomGenerator.Next(-30, 101);
return (n < 0) ? default : n.ToString();
case QuestionType.Text:
default:
switch (randomGenerator.Next(0, 5))
{
case 0:
return default;
case 1:
return "Red";
case 2:
return "Green";
case 3:
return "Blue";
}
return "Red. No, Green. Wait.. Blue... AAARGGGGGHHH!";
}
}
Der Speicher für die Antworten der Umfrage ist ein Dictionary<int, string>?, der angibt, dass er null sein kann. Sie verwenden das neue Sprachfeature, um Ihre Entwurfsabsicht sowohl für den Compiler als auch für alle Benutzer zu deklarieren, die Ihren Code später lesen. Wenn Sie surveyResponses jemals dereferenzieren, ohne zuerst den Wert von null zu überprüfen, erhalten Sie eine Compilerwarnung. Sie erhalten keine Warnung in der AnswerSurvey Methode, da der Compiler bestimmen kann, ob die surveyResponses Variable im vorherigen Code auf einen Wert ungleich Null festgelegt wurde.
Die Verwendung null für fehlende Antworten hebt einen wichtigen Punkt für die Arbeit mit nullablen Referenztypen hervor: Ihr Ziel ist nicht, alle null Werte aus Ihrem Programm zu entfernen. Stattdessen ist es Ihr Ziel, sicherzustellen, dass der von Ihnen geschriebene Code die Absicht Ihres Designs ausdrückt. Fehlende Werte sind ein notwendiges Konzept zum Ausdrücken in Ihrem Code. Der null Wert ist eine klare Möglichkeit, diese fehlenden Werte auszudrücken. Wenn Sie versuchen, alle null Werte zu entfernen, wird eine andere Möglichkeit definiert, um diese fehlenden Werte ohne nullauszudrücken.
Als Nächstes müssen Sie die Methode in der PerformSurveySurveyRun Klasse schreiben. Fügen Sie den folgenden Code in der SurveyRun Klasse hinzu:
private List<SurveyResponse>? respondents;
public void PerformSurvey(int numberOfRespondents)
{
int respondentsConsenting = 0;
respondents = new List<SurveyResponse>();
while (respondentsConsenting < numberOfRespondents)
{
var respondent = SurveyResponse.GetRandomId();
if (respondent.AnswerSurvey(surveyQuestions))
respondentsConsenting++;
respondents.Add(respondent);
}
}
Hier noch einmal gibt Die Auswahl einer Nullwerte List<SurveyResponse>? an, dass die Antwort möglicherweise null ist. Das bedeutet, dass die Umfrage noch nicht den Befragten gegeben wurde. Beachten Sie, dass die Befragten bis zu genügend Zustimmung hinzugefügt werden.
Der letzte Schritt zum Ausführen der Umfrage besteht darin, am Ende der Methode einen Aufruf zum Ausführen der Main Umfrage hinzuzufügen:
surveyRun.PerformSurvey(50);
Untersuchen von Umfrageantworten
Der letzte Schritt besteht darin, Umfrageergebnisse anzuzeigen. Sie fügen Code zu vielen der von Ihnen geschriebenen Klassen hinzu. Dieser Code veranschaulicht den Wert der Unterscheidung von nullablen und nicht nullablen Bezugstypen. Fügen Sie zunächst die folgenden zwei Ausdruckskörpermitglieder zur SurveyResponse Klasse hinzu:
public bool AnsweredSurvey => surveyResponses != null;
public string Answer(int index) => surveyResponses?.GetValueOrDefault(index) ?? "No answer";
Da surveyResponses ein Verweistyp ist, der NULL-Werte zulässt, sind vor dem Dereferenzieren NULL-Überprüfungen erforderlich. Die Answer Methode gibt eine nicht-nullbare Zeichenfolge zurück, daher müssen wir den Fall einer fehlenden Antwort mithilfe des Null-Koaleszenzoperators behandeln.
Fügen Sie als Nächstes diese drei Ausdruckskörperelemente zur SurveyRun Klasse hinzu:
public IEnumerable<SurveyResponse> AllParticipants => (respondents ?? Enumerable.Empty<SurveyResponse>());
public ICollection<SurveyQuestion> Questions => surveyQuestions;
public SurveyQuestion GetQuestion(int index) => surveyQuestions[index];
Das AllParticipants Element muss berücksichtigen, dass die respondents Variable möglicherweise null ist, der Rückgabewert darf jedoch nicht null sein. Wenn Sie diesen Ausdruck ändern, indem Sie ?? und die darauf folgende leere Sequenz entfernen, warnt Sie der Compiler, dass die Methode eventuell null zurückgeben könnte, während ihre Rückgabesignatur einen nicht nullfähigen Typ ausgibt.
Fügen Sie schließlich unten in der Main Methode die folgende Schleife hinzu:
foreach (var participant in surveyRun.AllParticipants)
{
Console.WriteLine($"Participant: {participant.Id}:");
if (participant.AnsweredSurvey)
{
for (int i = 0; i < surveyRun.Questions.Count; i++)
{
var answer = participant.Answer(i);
Console.WriteLine($"\t{surveyRun.GetQuestion(i).QuestionText} : {answer}");
}
}
else
{
Console.WriteLine("\tNo responses");
}
}
Sie benötigen keine null Prüfungen in diesem Code, da Sie die zugrunde liegenden Schnittstellen so entworfen haben, dass sie alle nicht-nullfähigen Verweistypen zurückgeben. Die statische Analyse des Compilers trägt dazu bei, sicherzustellen, dass diese Entwurfsverträge befolgt werden.
Code abrufen
Sie können den Code für das fertige Lernprogramm aus unserem Beispiel-Repository im Ordner "csharp/NullableIntroduction " abrufen.
Experimentieren Sie, indem Sie die Typdeklarationen zwischen nullablen und nicht nullablen Verweistypen ändern. Erfahren Sie, wie unterschiedliche Warnungen generiert werden, um sicherzustellen, dass Sie nicht versehentlich ein null dereferenzieren.
Nächste Schritte
Hier erfahren Sie, wie Sie Nullable-Verweistypen bei Verwendung von Entity Framework nutzen: