Erkunden der objektorientierten Programmierung mit Klassen und ObjektenExplore object oriented programming with classes and objects

In diesem Tutorial erstellen Sie eine Konsolenanwendung und die grundlegenden objektorientierten Funktionen, die Teil der C#-Sprache sind.In this tutorial, you'll build a console application and see the basic object-oriented features that are part of the C# language.

VoraussetzungenPrerequisites

Für dieses Tutorial wird vorausgesetzt, dass Sie einen Computer für die lokale Entwicklung eingerichtet haben.The tutorial expects that you have a machine set up for local development. Unter Windows, Linux oder macOS können Sie die .NET CLI zum Programmieren, Erstellen und Ausführen von Anwendungen verwenden.On Windows, Linux, or macOS, you can use the .NET CLI to create, build, and run applications. Unter Windows können Sie Visual Studio 2019 verwenden.On Windows, you can use Visual Studio 2019. Setupanweisungen finden Sie unter Einführung in .NET-Entwicklungstools.For setup instructions, see Set up your local environment.

Erstellen Ihrer AnwendungCreate your application

Erstellen Sie in einem Terminalfenster ein Verzeichnis namens classes.Using a terminal window, create a directory named classes. Dort werden Sie Ihre Anwendung erstellen.You'll build your application there. Wechseln Sie in dieses Verzeichnis, und geben Sie dotnet new console im Konsolenfenster ein.Change to that directory and type dotnet new console in the console window. Dieser Befehl erstellt die Anwendung.This command creates your application. Öffnen Sie Program.cs.Open Program.cs. Es sollte wie folgt aussehen:It should look like this:

using System;

namespace classes
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

In diesem Tutorial erstellen Sie neue Typen, die ein Bankkonto darstellen.In this tutorial, you're going to create new types that represent a bank account. Entwickler definieren jede Klasse in der Regel in einer anderen Textdatei.Typically developers define each class in a different text file. Dies erleichtert die Verwaltung bei zunehmender Programmgröße.That makes it easier to manage as a program grows in size. Erstellen Sie eine neue Datei mit dem Namen BankAccount.cs im Verzeichnis classes.Create a new file named BankAccount.cs in the classes directory.

Diese Datei enthält die Definition eines *Bankkontos _.This file will contain the definition of a *bank account _. In der objektorientierten Programmierung wird der Code organisiert, indem Typen in Form von _Klassen* erstellt werden.Object Oriented programming organizes code by creating types in the form of _*classes**. Diese Klassen enthalten den Code, der eine bestimmte Entität darstellt.These classes contain the code that represents a specific entity. Die BankAccount-Klasse stellt ein Bankkonto dar.The BankAccount class represents a bank account. Der Code implementiert bestimmte Vorgänge mittels Methoden und Eigenschaften.The code implements specific operations through methods and properties. In diesem Tutorial unterstützt das Bankkonto dieses Verhalten:In this tutorial, the bank account supports this behavior:

  1. Es enthält eine 10-stellige Zahl, die das Bankkonto eindeutig identifiziert.It has a 10-digit number that uniquely identifies the bank account.
  2. Es enthält eine Zeichenfolge, die den bzw. die Namen des Besitzers speichert.It has a string that stores the name or names of the owners.
  3. Der Kontostand kann abgerufen werden.The balance can be retrieved.
  4. Es akzeptiert Einzahlungen.It accepts deposits.
  5. Es akzeptiert Abbuchungen.It accepts withdrawals.
  6. Der anfängliche Kontostand muss positiv sein.The initial balance must be positive.
  7. Abbuchungen dürfen nicht in einem negativen Kontostand resultieren.Withdrawals cannot result in a negative balance.

Definieren des BankkontotypsDefine the bank account type

Sie können beginnen, indem Sie die Grundlagen einer Klasse erstellen, die dieses Verhalten definiert.You can start by creating the basics of a class that defines that behavior. Erstellen Sie eine neue Datei mit dem Befehl File:New.Create a new file using the File:New command. Nennen Sie sie BankAccount.cs.Name it BankAccount.cs. Fügen Sie der Datei BankAccount.cs folgenden Code hinzu:Add the following code to your BankAccount.cs file:

using System;

namespace classes
{
    public class BankAccount
    {
        public string Number { get; }
        public string Owner { get; set; }
        public decimal Balance { get; }

        public void MakeDeposit(decimal amount, DateTime date, string note)
        {
        }

        public void MakeWithdrawal(decimal amount, DateTime date, string note)
        {
        }
    }
}

Bevor wir fortfahren, lassen Sie uns anschauen, was Sie erstellt haben.Before going on, let's take a look at what you've built. Die namespace-Deklaration ist eine Möglichkeit, Ihren Code logisch zu organisieren.The namespace declaration provides a way to logically organize your code. Da dieses Tutorial relativ klein ist, platzieren Sie den gesamten Code in einen einzigen Namespace.This tutorial is relatively small, so you'll put all the code in one namespace.

public class BankAccount definiert die Klasse oder den Typ, die/den Sie erstellen.public class BankAccount defines the class, or type, you are creating. Sämtliche Inhalte zwischen { und }, die der Klassendeklaration folgen, definieren den Zustand und das Verhalten der Klasse.Everything inside the { and } that follows the class declaration defines the state and behavior of the class. Die BankAccount-Klasse verfügt über fünf *Member _.There are five *members _ of the BankAccount class. Die ersten drei sind Eigenschaften.The first three are properties. Eigenschaften sind Datenelemente und können Code aufweisen, der eine Überprüfung oder andere Regeln erzwingt.Properties are data elements and can have code that enforces validation or other rules. Die letzten beiden sind _*Methoden**.The last two are _*methods**. Methoden sind Codeblöcke, die eine einzelne Funktion ausführen.Methods are blocks of code that perform a single function. Das Lesen der Namen der einzelnen Member sollte Ihnen oder anderen Entwicklern genug Informationen liefern, um zu verstehen, welche Aufgabe die Klasse hat.Reading the names of each of the members should provide enough information for you or another developer to understand what the class does.

Eröffnen eines neuen KontosOpen a new account

Die erste zu implementierende Funktion ist das Eröffnen eines Bankkontos.The first feature to implement is to open a bank account. Wenn ein Kunde ein Konto eröffnet, muss er einen anfänglichen Kontostand bereitstellen und Informationen über den/die Besitzer dieses Kontos angeben.When a customer opens an account, they must supply an initial balance, and information about the owner or owners of that account.

Das Erstellen eines neuen Objekts des Typs BankAccount bedeutet, einen *Konstruktor _ zu definieren, der diese Werte zuweist.Creating a new object of the BankAccount type means defining a *constructor _ that assigns those values. Ein _ Konstruktor* ist ein Member, der den gleichen Namen wie die Klasse hat.A _ constructor* is a member that has the same name as the class. Er wird verwendet, um Objekte dieses Klassentyps zu initialisieren.It is used to initialize objects of that class type. Fügen Sie dem BankAccount-Typ den folgenden Konstruktor hinzu,.Add the following constructor to the BankAccount type. Platzieren Sie folgenden Code oberhalb der Deklaration von MakeDeposit:Place the following code above the declaration of MakeDeposit:

public BankAccount(string name, decimal initialBalance)
{
    this.Owner = name;
    this.Balance = initialBalance;
}

Konstruktoren werden bei der Erstellung eines Objekts mit new aufgerufen.Constructors are called when you create an object using new. Ersetzen Sie die Zeile Console.WriteLine("Hello World!"); in Program.cs durch den folgende Code (ersetzen Sie <name> durch Ihren Namen):Replace the line Console.WriteLine("Hello World!"); in Program.cs with the following code (replace <name> with your name):

var account = new BankAccount("<name>", 1000);
Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");

Wir führen nun aus, was wir bisher erstellt haben.Let's run what you've built so far. Wenn Sie Visual Studio verwenden, wählen Sie Ohne Debuggen starten im Menü Ausführen aus.If you're using Visual Studio, Select Start without debugging from the Run menu. Wenn Sie eine Befehlszeile verwenden, geben Sie dotnet run in dem Verzeichnis ein, wo Sie das Projekt erstellt haben.If you're using a command line, type dotnet run in the directory where you've created your project.

Haben Sie bemerkt, dass die Kontonummer leer ist?Did you notice that the account number is blank? Es ist höchste Zeit, dies zu ändern.It's time to fix that. Die Kontonummer sollten zugewiesen werden, wenn das Objekt erstellt wird.The account number should be assigned when the object is constructed. Jedoch sollte nicht der Aufrufende für das Erstellen verantwortlich sein.But it shouldn't be the responsibility of the caller to create it. Der BankAccount-Klassencode sollte wissen, wie neue Kontonummern zugewiesen werden.The BankAccount class code should know how to assign new account numbers. Eine einfache Möglichkeit hierzu ist, mit einer 10-stelligen Zahl zu beginnen.A simple way to do this is to start with a 10-digit number. Lassen Sie sie bei jeder Erstellung eines neuen Kontos erhöhen.Increment it when each new account is created. Speichern Sie schließlich die aktuelle Kontonummer, wenn ein Objekt erstellt wird.Finally, store the current account number when an object is constructed.

Fügen Sie der BankAccount-Klasse eine Memberdeklaration hinzu.Add a member declaration to the BankAccount class. Platzieren Sie die folgende Codezeile nach der öffnenden geschweiften Klammer { am Anfang der BankAccount-Klasse:Place the following line of code after the opening brace { at the beginning of the BankAccount class:

private static int accountNumberSeed = 1234567890;

Dies ist ein Datenelement.This is a data member. Es ist private, d.h. der Zugriff darauf ist nur über Code in der BankAccount-Klasse möglich.It's private, which means it can only be accessed by code inside the BankAccount class. Dies ist eine Möglichkeit, die öffentlichen Verantwortlichkeiten (z. B. Besitz einer Kontonummer) von der privaten Implementierung (wie Kontonummern generiert werden) zu trennen.It's a way of separating the public responsibilities (like having an account number) from the private implementation (how account numbers are generated). Es ist auch als static definiert, wird also von allen BankAccount-Objekten gemeinsam genutzt.It is also static, which means it is shared by all of the BankAccount objects. Der Wert einer nicht statischen Variable ist für jede Instanz des BankAccount-Objekts eindeutig.The value of a non-static variable is unique to each instance of the BankAccount object. Fügen Sie dem Konstruktor die folgenden zwei Zeilen hinzu, um die Kontonummer zuzuweisen.Add the following two lines to the constructor to assign the account number. Platzieren Sie sie nach der Zeile, die this.Balance = initialBalance enthält:Place them after the line that says this.Balance = initialBalance:

this.Number = accountNumberSeed.ToString();
accountNumberSeed++;

Geben Sie dotnet run ein, um die Ergebnisse anzuzeigen.Type dotnet run to see the results.

Erstellen von Einzahlungen und AbbuchungenCreate deposits and withdrawals

Um ordnungsgemäß zu funktionieren, muss Ihre Bankkontoklasse Einzahlungen und Abbuchungen akzeptieren.Your bank account class needs to accept deposits and withdrawals to work correctly. Einzahlungen und Abbuchungen implementieren Sie, indem Sie eine Erfassung jeder Transaktion für das Konto erstellen.Let's implement deposits and withdrawals by creating a journal of every transaction for the account. Dies ist vorteilhafter, als den Kontostand bei jeder Transaktion einfachen zu aktualisieren.That has a few advantages over simply updating the balance on each transaction. Der Verlauf kann zum Überwachen aller Transaktionen und Verwalten täglicher Kontostände verwendet werden.The history can be used to audit all transactions and manage daily balances. Indem der Kontostand ggf. aus dem Verlauf aller Transaktionen berechnet wird, werden etwaige Korrekturen von Fehlern in einer einzelnen Transaktion bei der nächsten Berechnung im Kontostand ordnungsgemäß widergespiegelt.By computing the balance from the history of all transactions when needed, any errors in a single transaction that are fixed will be correctly reflected in the balance on the next computation.

Zunächst erstellen wir einen neuen Typ, um eine Transaktion darzustellen.Let's start by creating a new type to represent a transaction. Dies ist ein einfacher Typ, der keine Verantwortlichkeiten hat.This is a simple type that doesn't have any responsibilities. Er benötigt einige Eigenschaften.It needs a few properties. Erstellen Sie eine neue Datei mit dem Namen Transaction.cs.Create a new file named Transaction.cs. Fügen Sie ihr folgenden Code hinzu:Add the following code to it:

using System;

namespace classes
{
    public class Transaction
    {
        public decimal Amount { get; }
        public DateTime Date { get; }
        public string Notes { get; }

        public Transaction(decimal amount, DateTime date, string note)
        {
            this.Amount = amount;
            this.Date = date;
            this.Notes = note;
        }
    }
}

Nun fügen wir eine List<T> von Transaction-Objekten der BankAccount-Klasse hinzu.Now, let's add a List<T> of Transaction objects to the BankAccount class. Fügen Sie die folgende Deklaration nach dem Konstruktor in ihrer BankAccount.cs-Datei hinzu:Add the following declaration after the constructor in your BankAccount.cs file:

private List<Transaction> allTransactions = new List<Transaction>();

Die List<T>-Klasse erfordert, dass Sie einen anderen Namespace importieren.The List<T> class requires you to import a different namespace. Fügen Sie am Anfang von BankAccount.cs Folgendes hinzu:Add the following at the beginning of BankAccount.cs:

using System.Collections.Generic;

Nun werden Sie Balance korrekt berechnen.Now, let's correctly compute the Balance. Der aktuelle Saldo kann durch Summieren der Werte aller Transaktionen ermittelt werden.The current balance can be found by summing the values of all transactions. Mit dem aktuellen Code können Sie nur den anfänglichen Saldo des Kontos abrufen. Sie müssen daher die Eigenschaft Balance aktualisieren.As the code is currently, you can only get the initial balance of the account, so you'll have to update the Balance property. Ersetzen Sie die Zeile public decimal Balance { get; } in BankAccount.cs durch den folgenden Code:Replace the line public decimal Balance { get; } in BankAccount.cs with the following code:

public decimal Balance
{
    get
    {
        decimal balance = 0;
        foreach (var item in allTransactions)
        {
            balance += item.Amount;
        }

        return balance;
    }
}

Dieses Beispiel zeigt einen wichtigen Aspekt der Eigenschaften.This example shows an important aspect of properties. Jetzt berechnen Sie den Kontostand, wenn ein anderer Programmierer den Wert anfordert.You're now computing the balance when another programmer asks for the value. Die Berechnung zählt alle Transaktionen auf und gibt die Summe als aktuellen Kontostand zurück.Your computation enumerates all transactions, and provides the sum as the current balance.

Implementieren Sie nun die MakeDeposit- und MakeWithdrawal-Methode.Next, implement the MakeDeposit and MakeWithdrawal methods. Diese Methoden erzwingen die letzten beiden Regeln: Der anfängliche Kontostand muss positiv sein, und eine Abbuchung darf nicht in einem negativen Kontostand resultieren.These methods will enforce the final two rules: that the initial balance must be positive, and that any withdrawal must not create a negative balance.

Dies führt das Konzept der Ausnahmen ein.This introduces the concept of exceptions. Standardmäßig wird eine Ausnahme ausgelöst, um anzuzeigen, dass eine Methode ihre Aufgabe nicht erfolgreich ausführen kann.The standard way of indicating that a method cannot complete its work successfully is to throw an exception. Der Typ der Ausnahme und die zugeordnete Nachricht beschreiben den Fehler.The type of exception and the message associated with it describe the error. Hier löst die MakeDeposit-Methode eine Ausnahme aus, wenn der Einzahlungsbetrag negativ ist.Here, the MakeDeposit method throws an exception if the amount of the deposit is negative. Die MakeWithdrawal-Methode löst eine Ausnahme aus, wenn der Abbuchungsbetrag negativ ist, oder wenn aus der Abbuchung ein negativer Kontostand resultiert.The MakeWithdrawal method throws an exception if the withdrawal amount is negative, or if applying the withdrawal results in a negative balance. Fügen Sie nach der Deklaration der allTransactions-Liste den folgenden Code hinzu:Add the following code after the declaration of the allTransactions list:

public void MakeDeposit(decimal amount, DateTime date, string note)
{
    if (amount <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(amount), "Amount of deposit must be positive");
    }
    var deposit = new Transaction(amount, date, note);
    allTransactions.Add(deposit);
}

public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
    if (amount <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
    }
    if (Balance - amount < 0)
    {
        throw new InvalidOperationException("Not sufficient funds for this withdrawal");
    }
    var withdrawal = new Transaction(-amount, date, note);
    allTransactions.Add(withdrawal);
}

Die throw-Anweisung löst eine Ausnahme aus.The throw statement throws an exception. Die Ausführung des aktuellen Block wird beendet, und die Steuerung wird an den ersten übereinstimmenden catch-Block übertragen, der in der Aufrufliste gefunden wurde.Execution of the current block ends, and control transfers to the first matching catch block found in the call stack. Sie fügen einen catch-Block hinzu, um diesen Code etwas später zu testen.You'll add a catch block to test this code a little later on.

Der Konstruktor sollte so geändert werden, dass er eine anfängliche Transaktion hinzufügt, anstatt den Kontostand direkt zu aktualisieren.The constructor should get one change so that it adds an initial transaction, rather than updating the balance directly. Da Sie die MakeDeposit-Methode bereits geschrieben haben, rufen Sie sie aus dem Konstruktor auf.Since you already wrote the MakeDeposit method, call it from your constructor. Der fertige Konstruktor sollte wie folgt aussehen:The finished constructor should look like this:

public BankAccount(string name, decimal initialBalance)
{
    this.Number = accountNumberSeed.ToString();
    accountNumberSeed++;

    this.Owner = name;
    MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
}

DateTime.Now ist eine Eigenschaft, die das aktuelle Datum und die Uhrzeit zurückgibt.DateTime.Now is a property that returns the current date and time. Testen Sie dies durch Hinzufügen von ein paar Einzahlungen und Abbuchungen in Ihrer Main-Methode und verfolgen Sie den Code, der einen neuen BankAccount erstellt:Test this by adding a few deposits and withdrawals in your Main method, following the code that creates a new BankAccount:

account.MakeWithdrawal(500, DateTime.Now, "Rent payment");
Console.WriteLine(account.Balance);
account.MakeDeposit(100, DateTime.Now, "Friend paid me back");
Console.WriteLine(account.Balance);

Testen Sie anschließend, ob Sie Fehlerbedingungen abfangen, indem Sie versuchen, ein Konto mit einem negativen Kontostand zu erstellen.Next, test that you are catching error conditions by trying to create an account with a negative balance. Fügen Sie den folgenden Code nach dem vorhergehenden Code hinzu:Add the following code after the preceding code you just added:

// Test that the initial balances must be positive.
try
{
    var invalidAccount = new BankAccount("invalid", -55);
}
catch (ArgumentOutOfRangeException e)
{
    Console.WriteLine("Exception caught creating account with negative balance");
    Console.WriteLine(e.ToString());
}

Sie verwenden die Anweisungen try und catch, um einen Codeblock zu markieren, der Ausnahmen auslösen kann, und um die erwarteten Fehler abzufangen.You use the try and catch statements to mark a block of code that may throw exceptions and to catch those errors that you expect. Mit dem gleichen Verfahren können Sie den Code testen, der bei einem negativen Kontostand eine Ausnahme auslöst.You can use the same technique to test the code that throws an exception for a negative balance. Fügen Sie den folgenden Code am Ende der Main-Methode hinzu:Add the following code at the end of your Main method:

// Test for a negative balance.
try
{
    account.MakeWithdrawal(750, DateTime.Now, "Attempt to overdraw");
}
catch (InvalidOperationException e)
{
    Console.WriteLine("Exception caught trying to overdraw");
    Console.WriteLine(e.ToString());
}

Speichern Sie die Datei, und geben Sie dotnet run zum Testen ein.Save the file and type dotnet run to try it.

Herausforderung – Protokollieren aller TransaktionenChallenge - log all transactions

Um dieses Tutorial abzuschließen, können Sie die GetAccountHistory-Methode schreiben, die eine Zeichenfolge (string) für den Transaktionsverlauf erstellt.To finish this tutorial, you can write the GetAccountHistory method that creates a string for the transaction history. Fügen Sie diese Methode dem BankAccount-Typ hinzu:Add this method to the BankAccount type:

public string GetAccountHistory()
{
    var report = new System.Text.StringBuilder();

    decimal balance = 0;
    report.AppendLine("Date\t\tAmount\tBalance\tNote");
    foreach (var item in allTransactions)
    {
        balance += item.Amount;
        report.AppendLine($"{item.Date.ToShortDateString()}\t{item.Amount}\t{balance}\t{item.Notes}");
    }

    return report.ToString();
}

Hier wird die StringBuilder-Klasse zum Formatieren einer Zeichenfolge verwendet, die eine Zeile für jede Transaktion enthält.This uses the StringBuilder class to format a string that contains one line for each transaction. Sie haben den Zeichenfolgen-Formatierungscode in diesen Tutorials bereits gesehen.You've seen the string formatting code earlier in these tutorials. \t ist ein neues Zeichen.One new character is \t. Damit wird ein Tabulator zum Formatieren der Ausgabe hinzugefügt.That inserts a tab to format the output.

Fügen Sie diese Zeile Program.cs zum Testen hinzu:Add this line to test it in Program.cs:

Console.WriteLine(account.GetAccountHistory());

Führen Sie das Programm aus, um die Ergebnisse zu sehen.Run your program to see the results.

Nächste SchritteNext steps

Wenn Sie nicht weiterkommen, sehen Sie sich die Quelle für dieses Tutorial in unserem GitHub-Repository an.If you got stuck, you can see the source for this tutorial in our GitHub repo.

Sie können mit dem Tutorial zur objektorientierten Programmierung fortfahren.You can continue with the object oriented programming tutorial.

Weitere Informationen zu diesen Begriffen finden Sie in diesen Artikeln:You can learn more about these concepts in these articles: