Effective-c#-4 使用框架

30 使用覆写而不是事件处理函数

如果基类已经有一些回调hook了,当然优先选择覆写它们来实现逻辑。其次才是添加事件监听。

31 使用IComparable\<T>和IComparer\<T>实现顺序关系

IComparable\<T>定义了类型的自然顺序,而IComparer\<T>则用来描述其他的顺序。

有一些老的API用的是IComparable而不是泛型版的IComparable\<T>,所以有时候要支持两种。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Example : IComparable<Example>, IComparable
{
private string name;

// 泛型版本
public int CompareTo(Example other)
{
return name.CompareTo(other.name);
}

/* 显式实现,避免被误使用
* 有额外的装箱拆箱操作
* 保证代码向后兼容
*/
public int IComparable.CompareTo(object obj)
{
if(!(obj is Example))
{
throw new ArgumentException("Argument is not a Example");
}
Example otherExample = obj as Example;
return this.CompareTo(otherExample)
}
}

// 调用
Example ex = new Example();
A a = new A();
ex.CompareTo(a); // 编译错误
(ex as IComparable).CompareTo(a); // 通过

(挖坑)

32 避免使用ICloneable接口

(挖坑)

33 仅用new修饰符处理基类更新

派生类可以使用new关键字来修饰某个方法,以达到覆盖基类同名方法的目的。但是这一操作并不能使基类方法变为虚方法,因故也就没有多态的作用。当以基类引用派生类时,所调用的就是基类的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Base{
void Func(){}
}

class Derived : Base{
void new Func(){}
}

// 调用
Derived d = new Derived();
d.Func(); // 调用Derived.Func版本
Base b = d as Base;
b.Func(); // 调用Base.Func版本

那么new关键字是为了解决什么问题呢?

假设sdk提供商提供了一个叫Base的类,你写了一个派生类Derived继承与它,顺便加上了你自己的一个方法MyFunc,用着很愉快,就这么平静地使用了几个月。几个月后你们需要对sdk进行更新适配,你突然发现sdk的Base类中同样也出现了一个MyFunc方法!于是你的代码编译报错了,因为派生类中的方法除非加了new关键字,否则不可以和基类方法同签名。

你有这么两种方案可以解决这个问题:

  1. 怕是Base类的Func是有其特殊用途的,我委屈一下把自己的Func名字改了
  2. 我觉得Base的Func这个方法根本没卵用,所以我给自己的Func加上new关键字,把Base.Func()覆盖了

34 尽量避免重载基类中定义的方法

这里说的是overload。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Base{}
class Derived : Base { }

class BaseWriter
{
public void Func(Derived d)
{
Console.WriteLine("Derived in BaseWriter");
}
}

class DerivedWriter : BaseWriter
{
public void Func(Base b)
{
Console.WriteLine("Base in DerivedWriter");
}
}

class Program
{
static void Main(string[] args)
{
DerivedWriter dWriter = new DerivedWriter();
dWriter.Func(new Derived());
}
}

上面的代码,最终的输出是什么呢?

答案是Base in DerivedWriter

原因是系统会优先在派生类中找最优重载方法。非常具有迷惑性,所以最好不要这么写。

如果想执行基类的方法,还需转成基类后再调用:

1
(dWriter as BaseWriter).Func(new Derived());

35~37 PLINQ并行编程注意事项

Buy Me A Coffee / 捐一杯咖啡的钱
分享这篇文章~
0%
//