此文是根据类和对象 - C# 基础教程 | Microsoft Learn进行实践的笔记。
BankAccount
类表示银行帐户。对账户进行分类
2.1
Transaction类此类用来记录每笔流水
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)
{
Amount = amount;
Date = date;
Notes = note;
}
}
2.2 BankAccount
类namespace Classes;
public class BankAccount
{
// 用一个 10 位数唯一标识银行帐户。
//用字符串存储一个或多个所有者名称。
//可以检索余额。
//接受存款。
//接受取款。
//初始余额必须是正数。
//取款后的余额不能是负数。
private static int accountNumberSeed = 1234567890;
private readonly decimal _minimumBalance;
public string Number { get; }
public string Owner { get; set; }
public decimal Balance { get
{
decimal balance = 0;
foreach (var item in allTransactions)
{
balance += item.Amount;
}
return balance;
}
}
//public BankAccount(string name, decimal initialBalance)
//{
// this.Owner = name;
// this.Number = accountNumberSeed.ToString();
// accountNumberSeed++;
// MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
//}
public BankAccount(string name, decimal initialBalance) : this(name, initialBalance, 0) { }
public BankAccount(string name, decimal initialBalance, decimal minimumBalance)
{
Number = accountNumberSeed.ToString();
accountNumberSeed++;
Owner = name;
_minimumBalance = minimumBalance;
if (initialBalance > 0)
MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
}
///
/// virtual 关键字在基类中声明一个方法,让派生类可以为该方法提供不同的实现。 在 virtual 方法种,任何派生类都可以选择重新实现。
/// 派生类使用 override 关键字定义新的实现。 通常将其称为“重写基类实现”。 virtual 关键字指定派生类可以重写此行为。
/// 还可以声明 abstract 方法,让派生类必须在其中重写此行为。 基类不提供 abstract 方法的实现。
///
public virtual void PerformMonthEndTransactions() { }
private List allTransactions = new 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 < _minimumBalance)
// {
// throw new InvalidOperationException("Not sufficient funds for this withdrawal");
// }
// var withdrawal = new Transaction(-amount, date, note);
// allTransactions.Add(withdrawal);
//}
public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
if (amount <= 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
}
Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance - amount < _minimumBalance);
Transaction? withdrawal = new(-amount, date, note);
allTransactions.Add(withdrawal);
if (overdraftTransaction != null)
allTransactions.Add(overdraftTransaction);
}
protected virtual Transaction? CheckWithdrawalLimit(bool isOverdrawn)
{
if (isOverdrawn)
{
throw new InvalidOperationException("Not sufficient funds for this withdrawal");
}
else
{
return default;
}
}
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();
}
}
其中包含了银行账户号码,用户,余额,以及此张卡最小的金额数(当卡是信用卡的时候,欠的金额后的余额)这四个属性。
private static int accountNumberSeed = 1234567890;
private readonly decimal _minimumBalance;
public string Number { get; }
public string Owner { get; set; }
public decimal Balance { get
{
decimal balance = 0;
foreach (var item in allTransactions)
{
balance += item.Amount;
}
return balance;
}
}
MakeWithdrawal取钱,MakeDeposit存钱
存钱和取钱的时候需要确保存钱的金额是大于0的,不然抛出异常。
取钱的特殊处理是,在信用卡有时候可以借钱,余额为负数只要在额度内,还可以借钱,不收费。但是如果超过了额度,仍然可以借钱,但是需要收取费用。这里的有两笔交易,交易可以为空,或者生成一个Transation的对象(因为计算余额的时候,是遍历Transaction的金额并进行相加)
Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance - amount < _minimumBalance);
Transaction? withdrawal = new(-amount, date, note);
这样返回的有时候是null,有时候是一个Transaction的对象。
注意这个CheckWithdrawalLimit在LineOfCreditAccount类中重写了。
这里CheckWithdrawalLimit 添加的方法是 protected
,这意味着只能从派生类中调用它。 该声明会阻止其他客户端调用该方法。 它还是 virtual
的,因此派生类可以更改行为。 返回类型为 Transaction?
。 ?
批注指示该方法可能返回 null
。
private List allTransactions = new 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 < _minimumBalance)
// {
// throw new InvalidOperationException("Not sufficient funds for this withdrawal");
// }
// var withdrawal = new Transaction(-amount, date, note);
// allTransactions.Add(withdrawal);
//}
public void MakeWithdrawal(decimal amount, DateTime date, string note)
{
if (amount <= 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "Amount of withdrawal must be positive");
}
Transaction? overdraftTransaction = CheckWithdrawalLimit(Balance - amount < _minimumBalance);
Transaction? withdrawal = new(-amount, date, note);
allTransactions.Add(withdrawal);
if (overdraftTransaction != null)
allTransactions.Add(overdraftTransaction);
}
protected virtual Transaction? CheckWithdrawalLimit(bool isOverdrawn)
{
if (isOverdrawn)
{
throw new InvalidOperationException("Not sufficient funds for this withdrawal");
}
else
{
return default;
}
}
BankAccount()构造函数是与类同名的成员。 用于初始化相应类类型的对象。会根据参数选择不同的构造方法,这称作构造函数的重载。 (构造方法具体可以参考:(7条消息) 什么是构造方法,构造方法的特征,作用_羡羡ˇ的博客-CSDN博客_什么是构造方法?构造方法有哪些特点?)
public BankAccount(string name, decimal initialBalance) : this(name, initialBalance, 0) { }
public BankAccount(string name, decimal initialBalance, decimal minimumBalance)
{
Number = accountNumberSeed.ToString();
accountNumberSeed++;
Owner = name;
_minimumBalance = minimumBalance;
//初始余额大于0等于你存进了第一笔钱
if (initialBalance > 0)
MakeDeposit(initialBalance, DateTime.Now, "Initial balance");
}
第一个构造函数适用于储蓄卡
第二个适用于借记卡
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();
}
上面 记录所有交易
分为此三类
其中的每个类都从其共享的基类( BankAccount
类)继承共享的行为。 为的每个派生类中的新增和不同功能编写实现。 这些派生类已具有 BankAccount
类中定义的所有行为。
virtual
关键字在基类中声明一个方法,让派生类可以为该方法提供不同的实现。 在 virtual
方法种,任何派生类都可以选择重新实现。 派生类使用 override
关键字定义新的实现。 通常将其称为“重写基类实现”。 virtual
关键字指定派生类可以重写此行为。 还可以声明 abstract
方法,让派生类必须在其中重写此行为。 基类不提供 abstract
方法的实现。
using Classes;
//红利帐户:
//将获得月末余额 5 % 的额度
public class InterestEarningAccount : BankAccount
{
public InterestEarningAccount(string name, decimal initialBalance) : base(name, initialBalance)
{
}
///
/// 派生类使用 override 关键字定义新的实现
///
public override void PerformMonthEndTransactions()
{
if (Balance > 500m)
{
decimal interest = Balance * 0.05m;
MakeDeposit(interest, DateTime.Now, "apply monthly interest");
}
}
}
using Classes;
//每月最后一天,可以充值一次指定的金额
public class GiftCardAccount : BankAccount
{
private readonly decimal _monthlyDeposit = 0m;
public GiftCardAccount(string name, decimal initialBalance, decimal monthlyDeposit = 0) : base(name, initialBalance)
=> _monthlyDeposit = monthlyDeposit;
public override void PerformMonthEndTransactions()
{
if (_monthlyDeposit != 0)
{
MakeDeposit(_monthlyDeposit, DateTime.Now, "Add monthly deposit");
}
}
}
using Classes;
//信用帐户:
//余额可以为负,但不能大于信用限额的绝对值。
//如果月末余额不为 0,每个月都会产生利息。
//将在超过信用限额的每次提款后收取费用
public class LineOfCreditAccount : BankAccount
{
public LineOfCreditAccount(string name, decimal initialBalance) : base(name, initialBalance)
{
if (Balance < 0)
{
// Negate the balance to get a positive interest charge:
decimal interest = -Balance * 0.07m;
MakeWithdrawal(interest, DateTime.Now, "Charge monthly interest");
}
}
public LineOfCreditAccount(string name, decimal initialBalance, decimal creditLimit) : base(name, initialBalance, -creditLimit)
{
}
// 对超过限额的取款进行收费,而不是拒绝交易。
protected override Transaction? CheckWithdrawalLimit(bool isOverdrawn) =>
isOverdrawn
? new Transaction(-20, DateTime.Now, "Apply overdraft fee")
: default;
}
namespace Classes
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var account = new BankAccount("", 1000);
Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");
account.MakeWithdrawal(500, DateTime.Now, "Rent payment");
Console.WriteLine(account.Balance);
account.MakeDeposit(100, DateTime.Now, "Friend paid me back");
Console.WriteLine(account.Balance);
Console.WriteLine(account.GetAccountHistory());
var account1 = new BankAccount("lianhua", 1040);
Console.WriteLine($"Account {account1.Number} was created for {account1.Owner} with {account1.Balance} initial balance.");
Console.WriteLine(account1.GetAccountHistory());
Console.WriteLine("_______________________________________");
var giftCard = new GiftCardAccount("gift card", 100, 50);
Console.WriteLine($"Account {giftCard.Number} was created for {giftCard.Owner} with {giftCard.Balance} initial balance.");
giftCard.MakeWithdrawal(20, DateTime.Now, "get expensive coffee");
giftCard.MakeWithdrawal(50, DateTime.Now, "buy groceries");
giftCard.PerformMonthEndTransactions();
// can make additional deposits:
giftCard.MakeDeposit(27.50m, DateTime.Now, "add some additional spending money");
Console.WriteLine(giftCard.GetAccountHistory());
var savings = new InterestEarningAccount("savings account", 10000);
Console.WriteLine($"Account {savings.Number} was created for {savings.Owner} with {savings.Balance} initial balance.");
savings.MakeDeposit(750, DateTime.Now, "save some money");
savings.MakeDeposit(1250, DateTime.Now, "Add more savings");
savings.MakeWithdrawal(250, DateTime.Now, "Needed to pay monthly bills");
savings.PerformMonthEndTransactions();
Console.WriteLine(savings.GetAccountHistory());
Console.WriteLine("____________________________");
var lineOfCredit1 = new LineOfCreditAccount("line of credit", 0);
Console.WriteLine($"Account {lineOfCredit1.Number} was created for {lineOfCredit1.Owner} with {lineOfCredit1.Balance} initial balance.");
var lineOfCredit = new LineOfCreditAccount("line of credit", 0, 2000);
Console.WriteLine($"Account {lineOfCredit.Number} was created for {lineOfCredit.Owner} with {lineOfCredit.Balance} initial balance.");
// How much is too much to borrow?
lineOfCredit.MakeWithdrawal(1000m, DateTime.Now, "Take out monthly advance");
lineOfCredit.MakeDeposit(50m, DateTime.Now, "Pay back small amount");
lineOfCredit.MakeWithdrawal(5000m, DateTime.Now, "Emergency funds for repairs");
lineOfCredit.MakeDeposit(150m, DateTime.Now, "Partial restoration on repairs");
lineOfCredit.PerformMonthEndTransactions();
Console.WriteLine(lineOfCredit.GetAccountHistory());
Test that the initial balances must be positive.
//BankAccount invalidAccount;
//try
//{
// invalidAccount = new BankAccount("invalid", -55);
//}
//catch (ArgumentOutOfRangeException e)
//{
// Console.WriteLine("Exception caught creating account with negative balance");
// Console.WriteLine(e.ToString());
// return;
//}
}
}
}
Hello World!
Account 1234567890 was created for with 1000 initial balance.
500
600
Date Amount Balance Note
2022/11/11 1000 1000 Initial balance
2022/11/11 -500 500 Rent payment
2022/11/11 100 600 Friend paid me back
Account 1234567891 was created for lianhua with 1040 initial balance.
Date Amount Balance Note
2022/11/11 1040 1040 Initial balance
_______________________________________
Account 1234567892 was created for gift card with 100 initial balance.
Date Amount Balance Note
2022/11/11 100 100 Initial balance
2022/11/11 -20 80 get expensive coffee
2022/11/11 -50 30 buy groceries
2022/11/11 50 80 Add monthly deposit
2022/11/11 27.50 107.50 add some additional spending money
Account 1234567893 was created for savings account with 10000 initial balance.
Date Amount Balance Note
2022/11/11 10000 10000 Initial balance
2022/11/11 750 10750 save some money
2022/11/11 1250 12000 Add more savings
2022/11/11 -250 11750 Needed to pay monthly bills
2022/11/11 587.50 12337.50 apply monthly interest
____________________________
Account 1234567894 was created for line of credit with 0 initial balance.
Account 1234567895 was created for line of credit with 0 initial balance.
Date Amount Balance Note
2022/11/11 -1000 -1000 Take out monthly advance
2022/11/11 50 -950 Pay back small amount
2022/11/11 -5000 -5950 Emergency funds for repairs
2022/11/11 -20 -5970 Apply overdraft fee
2022/11/11 150 -5820 Partial restoration on repairs
C:\...\net6.0\PracticeBasic.exe (process 9104) exited with code 0.
Press any key to close this window . . .