假设我们要为某大学写一个工资管理程序。首先是表示员工的 Employee 类(Employee.cs):
01: namespace Skyiv.Ben
02: {
03: class Employee
04: {
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.Ben
02: {
03: class Department
04: {
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.Ben
05: {
06: class Program
07: {
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: }
这个程序的运行结果如下所示:
三闾大学工资明细表:
校长室 高松年 工资:72,767.58
政治系 方鸿渐 工资:31,982.45
政治系 赵辛楣 工资:40,126.31
加薪之后:
校长室 高松年 工资:82,767.58
政治系 方鸿渐 工资:41,982.45
政治系 赵辛楣 工资:50,126.31
三闾大学工资统计表:
校长室 人数:1 总工资:82,767.58
政治系 人数:2 总工资:92,108.76
如果我们把 Employee 类(class)改为结构(struct),则在编译时就会报以下错误:
CS1612: 无法修改“System.Collections.Generic.List.this[int]”的返回值,因为它不是变量。
这个错误发生在 Program.cs 第 33 行中的 employees[i].Salary += 10000; 语句。
我不理解这个 CS1612 错误,如果哪位朋友能够解释一下,请在评论中给出。谢谢!
如果我们把 Department 类(class)改为结构(struct):
01: namespace Skyiv.Ben
02: {
03: struct Department
04: {
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# 编译器 <http://www.cnblogs.com/skyivben/archive/2009/05/09/1453007.html>)。
再次运行该程序,运行结果的最后三行如下所示:
三闾大学工资统计表:
校长室 人数:0 总工资:0.00
政治系 人数:0 总工资:0.00
这是因为现在的 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))
评论 {{userinfo.comments}}
{{child.content}}
{{question.question}}
提交