假设我们要为某大学写一个工资管理程序。首先是表示员工的 Employee 类(Employee.cs):
01: namespace Skyiv.Ben02: {03: class Employee04: {05: public string Department { get; private set; }06: public string Name { get; private set; }07: public decimal Salary { get; set; }08: 09: public Employee(string department, string name, decimal salary)10: {11: Department = department;12: Name = name;13: Salary = salary;14: }15: 16: public override string ToString()17: {18: return string.Format("{0} {1} 工资:{2:N2}", Department, Name, Salary);19: }20: }21: }
接着是表示学校中各系的 Department 类(Department.cs):
01: namespace Skyiv.Ben02: {03: class Department04: {05: public string Name { get; private set; }06: public int Count { get; private set; }07: public decimal TotalSalary { get; private set; }08: 09: public Department(string name)10: {11: Name = name;12: }13: 14: public void Add(Employee employee)15: {16: Count++;17: TotalSalary += employee.Salary;18: }19: 20: public override string ToString()21: {22: return string.Format("{0} 人数:{1} 总工资:{2:N2}", Name, Count, TotalSalary);23: }24: }25: }
最后就是主程序 Program.cs :
01: using System;02: using System.Collections.Generic;03: 04: namespace Skyiv.Ben05: {06: class Program07: {08: static void Main()09: {10: new Program().Run();11: }12: 13: void Run()14: {15: var employees = InitializeEmployees();16: SalaryRaise(employees);17: Statistic(employees);18: }19: 20: List<Employee> InitializeEmployees()21: {22: var employees = new List<Employee>();23: employees.Add(new Employee("校长室", "高松年", 72767.58m));24: employees.Add(new Employee("政治系", "方鸿渐", 31982.45m));25: employees.Add(new Employee("政治系", "赵辛楣", 40126.31m));26: Console.WriteLine("三闾大学工资明细表:");27: employees.ForEach(e => Console.WriteLine(e));28: return employees;29: }30: 31: void SalaryRaise(List<Employee> employees)32: {33: for (var i = 0; i < employees.Count; i++) employees[i].Salary += 10000;34: Console.WriteLine(Environment.NewLine + "加薪之后:");35: employees.ForEach(e => Console.WriteLine(e));36: }37: 38: void Statistic(List<Employee> employees)39: {40: var departments = new Dictionary<string, Department>();41: foreach (var employee in employees)42: {43: var name = employee.Department;44: Department dep;45: if (!departments.TryGetValue(name, out dep)) departments.Add(name, dep = new Department(name));46: dep.Add(employee);47: }48: Console.WriteLine(Environment.NewLine + "三闾大学工资统计表:");49: foreach (var kvp in departments) Console.WriteLine(kvp.Value);50: }51: }52: }
这个程序的运行结果如下所示:
如果我们把 Employee 类(class)改为结构(struct),则在编译时就会报以下错误:
这个错误发生在 Program.cs 第 33 行中的 employees[i].Salary += 10000; 语句。
我不理解这个 CS1612 错误,如果哪位朋友能够解释一下,请在评论中给出。谢谢!
如果我们把 Department 类(class)改为结构(struct):
01: namespace Skyiv.Ben02: {03: struct Department04: {05: public string Name { get; private set; }06: public int Count { get; private set; }07: public decimal TotalSalary { get; private set; }08: 09: public Department(string name) : this()10: {11: Name = name;12: }13: 14: public void Add(Employee employee)15: {16: Count++;17: TotalSalary += employee.Salary;18: }19: 20: public override string ToString()21: {22: return string.Format("{0} 人数:{1} 总工资:{2:N2}", Name, Count, TotalSalary);23: }24: }25: }
注意上述程序中第 09 行最后要加上“ : this() ”,否则 Microsoft C# 编译器会报错(但是 Mono C# 编译器不会报错,请参见:浅谈 Microsoft C# 编译器和 Mono C# 编译器)。
再次运行该程序,运行结果的最后三行如下所示:
这是因为现在的 Department 结构是值类型,而不是引用类型。所以在 Program.cs 第 46 行的 dep.Add(employee); 语句中,dep 的值的更改不会影响到 departments 字典中的值。所以统计出来的人数和总工资都是零了。
要绕过这个陷阱很简单,在第 46 行的 dep.Add(employee); 语句后面加一句 departments[name] = dep; 就行了。
在 .NET Framework Base Class Library 中,有很多的结构(struct)。如:
- System.Int32
- System.DateTime
- System.Drawing.Size
使用时也要小心陷阱。
此外,还有注意 DateTime 的 Add 和 AddDays 等方法并不更改此 DateTime 的值。而是返回一个新的 DateTime,其值是此运算的结果。因此以下语句是不成立的:
for (var date = DateTime.MinValue; date < DateTime.Today; date.AddDays(1))
正确的应该是:
for (var date = DateTime.MinValue; date < DateTime.Today; date = date.AddDays(1))
版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。
- 2楼u010786678昨天 14:07
- 谢谢小伙伴的分享,学习了`(*∩_∩*)′
- 1楼u010786678昨天 14:04
- 谢谢小伙伴的分享,学习了`(*∩_∩*)′