代码改变世界

.net 知识补充 注意点

2011-02-12 15:07  Clingingboy  阅读(471)  评论(0编辑  收藏  举报

 

一.关于装箱与拆箱

看这两篇文章

http://www.cnblogs.com/mqsuper/archive/2008/08/12/1265520.html

http://www.cnblogs.com/wjiang/archive/2010/12/29/1920474.html

需要注意的点

  1. 尽量使用泛型集合
  2. 方法传参数时注意数据类型,减少装箱次数
  3. 结构体需要整体替换改变,内部属性改变无效
  4. 不要使用值类型和字符串相加(以前这被认为是一个技巧),会导致装箱

二.对象的相等性和同一性

int a = 1;
int b = 1;
Console.WriteLine(a.Equals(b));
Console.WriteLine(ReferenceEquals(a, b));

对象的Equals方法可以重写,所以无法得知相等性,ReferenceEquals则比较引用地址

image

有没发现ReferenceEquals使得值类型又装箱了

==与!=通常会调用内部的Equals方法

三.Dispose模式

参考此篇文章

http://www.cnblogs.com/wing011203/archive/2010/01/14/1648176.html

即为了防止用户忘记手动释放非托管资源,而在析构函数中释放资源.

当然也可以手动释放,dispose模式遵照着一定的规则,并没什么奥妙.之前我的理解是如何不通过在析构函数中自动调用Dispose方法,这个想法是错误的.还是通过析构函数中调用Dispose方法.仅仅需要记住其实现的步骤就可以了。

四.显式隐藏从基类继承的成员

public class A
{
    public void Test()
    {
        Console.WriteLine("A");
    }
}

public class B : A
{
    new public void Test()
    {
        Console.WriteLine("B");
    }
}

public class C : B
{
    new public void Test()
    {
        Console.WriteLine("c");
    }
}

public static void Main()
{
    A a = new B();
    a.Test();
    A b = new C();
    b.Test();

image

五.常量

除非确定不会更改,否则不要用常量.常量如静态字段,但不用static关键字,

public const int aa = 1;

需要注意的是,若其他程序集使用了这个常量,若重新修改这个常量重新编译,其他程序集也不会起作用,也需要重新编译.

六.事件引发

主要在于变量的判定问题。

版本一.

public event EventHandler Click;

private void OnClick(EventArgs e)
{
    if (Click != null) Click(this, e);
}

在多线程情景下,Click作为一个公开事件可能在一个线程中事件尚未触发完成,但在另一个线程中则移除了这个事件,就会导致Click事件变为空.所以更正如下

private void OnClick(EventArgs e)
{
    var temp = Click;
    if (temp != null) temp(this, e);
}

使用内部的一个变量,则可以修正这个错误。

七.事件的实质

事件的本质就是委托回调.当定义了一个事件后,编译器会生成相关代码。

public void add_Click(EventHandler value)
{
    EventHandler handler2;
    EventHandler click = this.Click;
    do
    {
        handler2 = click;
        EventHandler handler3 = (EventHandler)Delegate.Combine(handler2, value);
        click = Interlocked.CompareExchange<EventHandler>(ref this.Click, handler3, handler2);
    }
    while (click != handler2);
}

public void remove_Click(EventHandler value)
{
    EventHandler handler2;
    EventHandler click = this.Click;
    do
    {
        handler2 = click;
        EventHandler handler3 = (EventHandler)Delegate.Remove(handler2, value);
        click = Interlocked.CompareExchange<EventHandler>(ref this.Click, handler3, handler2);
    }
    while (click != handler2);
}

以上以线程安全的方式来添加和移除一个委托,所以添加事件和注销事件就是对委托的操作。

八.显示的事件实现

若不使用.net内置的事件语法,可以直接通过操作委托来实现一套事件管理机制.

可以参考上述事件的实现方式,将委托存在Dictionary中.具体参考CLR VIA C#(第3版)