现在的位置: 首页 > 综合 > 正文

More Effective C# Item9 :使用泛型元组代替out和ref参数

2012年05月05日 ⁄ 综合 ⁄ 共 1842字 ⁄ 字号 评论关闭

    如果我们在进行设计时,需要针对一个方法返回多个结果,通常情况下,我们会使用ref或者out参数。同时,我们还是使用泛型元组来返回多个不相关的值。

    我们来看下面的代码,首先定义一个具有继承关系的结构。

代码

1 publicclass Person
2 {
3 privatereadonlystring m_strName;
4 publicstring Name
5 {
6 get { return m_strName; }
7 }
8
9 public Person(string name)
10 {
11 m_strName = name;
12 }
13
14 publicoverridestring ToString()
15 {
16 returnstring.Format("Name:{0}", m_strName);
17 }
18 }
19
20 publicclass Employee : Person
21 {
22 privatereadonly Decimal m_deSalary;
23 public Decimal Salary
24 {
25 get { return m_deSalary; }
26 }
27
28 public Employee(string name, decimal salary)
29 : base(name)
30 {
31 m_deSalary = salary;
32 }
33
34 publicoverridestring ToString()
35 {
36 returnstring.Format("Name:{0}, Salary:{1}", base.Name, m_deSalary);
37 }
38 }

    下面是测试代码。

代码

1 privatestaticvoid Test()
2 {
3 Employee emp =new Employee("Wing", 1000);
4 ChangeName(ref emp, "UnKnown", 2000);
5
6 Person person =new Person("Wing");
7 ChangeName(ref person, "UnKnown");
8 }
9
10 privatestaticvoid ChangeName(ref Employee emp, string newName, Decimal newSalary)
11 {
12 Console.WriteLine(emp);
13 emp =new Employee(newName, newSalary);
14 Console.WriteLine(emp);
15 }
16
17 privatestaticvoid ChangeName(ref Person person, string newName)
18 {
19 Console.WriteLine(person);
20 person =new Person(newName);
21 Console.WriteLine(person);
22 }

    我们来看一下使用ref和out时的限制,首先,使用ref参数,很难创建不可变的对象;其次,使用ref参数,很难实现多态,因为ref参数不支持隐式类型转换。例如上面代码中,我们需要定义两个ChangName方法,针对ChangName(Person person)时,传入Employee类型的对象,否则,就会报编译错误。

    其实ref参数和返回值的区别也在此,方法的返回值是可以支持隐式类型转换的,可以将返回值设置为父类型,然后在实际运行时,返回子类型。

    那么如何避免使用ref参数呢,我们可以使用元组,即Tuple。

    我们可以看以下的代码。

1 private static Tuple<string, Decimal> GetEmpInfo(Employee emp)
2 {
3     return new Tuple<string, Decimal>(emp.Name, emp.Salary);
4 }

    或许上面的代码只是重新调整了一下方法的签名,但是当你逐渐熟悉使用函数式编程结构时,你就会发现这个技术的重要性。接受out或者ref参数的方法无法与其他方法良好的组合在一起,而返回单一值(无论多复杂)的方法则能很好的进行组合。

    ref和out参数表明方法中可以创建出符合声明类型的对象,多态表明派生类总是可以代替基类。不过当方法中需要创建出返回值对象时,上述说法还包含了一些新的含义。当调用代码期待基类对象时,很多情况下方法中都会创建出派生类型对象。总的来说,上述两条规则意味着,out和ref参数无法真正的使用到多态,若是改为使用泛型元组返回多个值,那么你的算法逻辑会更易于使用。

抱歉!评论已关闭.