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.
Häufig können mehrere Algorithmen oder Implementierungen dieselbe Aufgabe richtig lösen. Der von Ihnen ausgewählte Code kommuniziert ein Design. Developer und Coding Agents, die Ihren Code lesen, leiten aus dessen Struktur Ihre Absicht ab: Was die einzelnen Operationen benötigen, wo sie hingehören und wann sie ausgeführt werden.
Tip
Dieser Artikel ist Teil des Abschnitts "Grundlagen" für Entwickler, die grundlegende C#-Ausdrücke, -Anweisungen und -Methoden kennen. Wenn Sie noch nicht mit der Programmierung vertraut sind, beginnen Sie zuerst mit den Lernprogrammen " Erste Schritte ".
In diesem Abschnitt werden gültige Ansätze zu Algorithmen verglichen und subtile Unterschiede in ihrem Verhalten und wie Leser sie interpretieren erläutert. Sie kombinieren vertraute Sprachelemente, z. B. Typen, Ausdrücke, Anweisungen und Methoden, und wählen Formen aus, die das gewünschte Design vermitteln.
Verhalten und Entwurfsabsicht vergleichen
Bevor Sie eine Implementierung auswählen, überlegen Sie, wie anderer Code sie verwenden wird. Dieser Code ist der Aufrufer: Er liefert Eingaben, ruft Ihre Operation auf und verwendet die Ergebnisse. Benötigt es ein abgeschlossenes Ergebnis sofort, oder kann es Werte einzeln verarbeiten? Ist eine Hilfsfunktion ausschließlich für diesen Vorgang vorgesehen, oder wird sie auch bei anderen Vorgängen verwendet? Diese Fragen helfen Ihnen, sowohl das benötigte Verhalten als auch das Design zu vergleichen, das Ihr Code vermittelt.
Ein kurzer Inlinevorgang zeigt den Lesern die Schritte direkt bei der Verwendung an. Beispielsweise macht Where(task => task.Priority > 3) die Filterregel sofort sichtbar. Ein benanntes Hilfsprogramm wie in Where(IsUrgent) betont den Zweck der Regel und ermöglicht Lesern, seine Details separat zu prüfen. Wählen Sie basierend darauf, ob die Schritte oder deren Zweck den umgebenden Code am besten erläutern.
Wo Sie eine Hilfsfunktion deklarieren, macht ihren beabsichtigten Geltungsbereich deutlich. Eine lokale Funktion in ShowDashboard gibt an, dass die Hilfsfunktion zu dieser Operation gehört und verhindert, dass andere Member sie aufrufen. Eine private Methode für den enthaltenden Typ stellt die Hilfsmethode anderen Membern zur Verfügung, was darauf hindeutet, dass Sie eine Wiederverwendung an anderer Stelle im Typ erwarten. Beide können dieselbe Berechnung darstellen, wecken beim Leser jedoch unterschiedliche Erwartungen hinsichtlich ihrer Bedeutung.
Die Art und Weise, wie Sie die Eingaben einer Hilfsfunktion bereitstellen, gibt Aufschluss über deren Abhängigkeiten. Durch die Übergabe eines Grenzwerts als Parameter, z. B. IsUrgent(task, minimumPriority), wird diese Eingabe bei jedem Aufruf verfügbar. Eine lokale Funktion oder Lambda-Funktion kann stattdessen die Variable aus dem umgebenden Bereich capturenminimumPriority, ohne sie als Argument zu empfangen. Capture verbindet die Hilfsfunktion mit dem Kontext des enthaltenden Vorgangs. Explizite Parameter erleichtern die Identifizierung der bereitgestellten Daten. Verwenden Sie eine static lokale Funktion oder Lambda-Funktion, wenn Sie erzwingen möchten, dass der umgebende Zustand nicht erfasst wird.
Wie Sie Ergebnisse zurückliefern, macht deutlich, wann die Arbeit stattfindet. Eine Methode, die eine Auflistung erstellt und zurückgibt, schließt diese Arbeit ab, bevor der Aufrufer die Auflistung empfängt. Ein Iterator erzeugt Elemente, wenn der Aufrufer sie anfordert, sodass der Aufrufer stoppen kann, bevor alle Elemente erstellt werden. Beide können dieselben Werte erzeugen, aber Anrufer müssen verstehen, ob sie abgeschlossene Ergebnisse erhalten oder eine Sequenz, deren Berechnung noch voraus liegt.
Identifizieren Sie für jede Auswahl zuerst das Verhalten, das der aufrufende Code benötigt. Überlegen Sie dann, welche Schlussfolgerungen ein anderer Developer oder Coding Agent aus dem Namen, dem Anwendungsbereich, den Eingaben und dem Ergebnis ziehen wird. Wählen Sie eine Form, die diese Erwartungen mit Ihrem Design in Einklang bringt, und erläutern Sie wichtige Verhaltensweisen, die sich allein aus der Struktur des Codes nicht ableiten lassen. Ziel ist es, eine bewusste Wahl zwischen gültigen Alternativen zu treffen und nicht dazu, überall eine Form anzuwenden.
Designoptionen in einem Beispiel lesen
Im folgenden Beispiel wird veranschaulicht, wie verschiedene Optionen verschiedene Teile eines Designs vermitteln. Es zeigt Aufgaben an, die dringend sind und bereit für den Start sind. A ProjectTask enthält den Titel, die Priorität und den blockierten Status einer Aufgabe.
var tasks = new[]
{
new ProjectTask("Confirm venue", Priority: 3, IsBlocked: false),
new ProjectTask("Print badges", Priority: 2, IsBlocked: true),
new ProjectTask("Test microphones", Priority: 2, IsBlocked: false),
};
ShowDashboard("Community meetup", tasks, minimumPriority: 2);
static void ShowDashboard(
string projectName,
IEnumerable<ProjectTask> tasks,
int minimumPriority)
{
var urgentTasks = tasks.Where(
task => task.Priority >= minimumPriority);
foreach (ProjectTask task in ReadyTasks(urgentTasks))
{
Console.WriteLine(FormatTask(task));
}
string FormatTask(ProjectTask task) =>
$"{projectName}: {task.Title}";
}
static IEnumerable<ProjectTask> ReadyTasks(
IEnumerable<ProjectTask> tasks)
{
foreach (ProjectTask task in tasks)
{
if (!task.IsBlocked)
{
yield return task;
}
}
}
record ProjectTask(string Title, int Priority, bool IsBlocked);
Jede Auswahl macht einen anderen Teil der Arbeit klar ersichtlich:
- Die an
Whereübergebene Lambda-Funktion platziert eine kurze Prioritätsregel neben der Operation, die sie verwendet. - Die lokale Funktion
FormatTaskbenennt einen Formatierungsschritt, der ausschließlich zuShowDashboardgehört. - Mit dem Iterator
ReadyTasksermöglicht es Aufrufern, fertige Aufgaben zu verarbeiten, ohne eine Zwischensammlung anzulegen. - Die
foreachSchleife macht die letzte Aktion, das Schreiben jedes Ergebnisses, explizit.
Zum Vergleich könnte ReadyTasksWhere(static task => !task.IsBlocked) ersetzen, da dieser Bereitschaftstest ein einfacher Filter ist. Beide Formulare wenden den Filter erst bei der Enumeration an. Die Lambda-Funktion platziert die Regel an der Aufrufstelle; ReadyTasks gibt der Regel einen Namen. Entscheiden Sie sich für eine der beiden Optionen, je nachdem, welche Informationen den Lesern helfen, den Anrufer besser zu verstehen.
Die folgenden Artikel verwenden Vergleiche wie diese, um zu erläutern, wann jeder Ansatz passt und was Leser aus Ihrer Wahl ableiten können.