此文是根据类和对象 - 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 . . .