技巧1.使用EventHanlderList代替EventHandler 

 

        以Control的Init事件为例。通常我们会简单的用一个语句来定义事件:

public event EventHandler Init;

        然而我们看实际的代码却是:

[WebSysDescription("Control_OnInit")]
public event EventHandler Init
{
    add
    {
        
this.Events.AddHandler(EventInit, value);
    }
    remove
    {
        
this.Events.RemoveHandler(EventInit, value);
    }
}

         Events属性就是EventHandlerList类型的对象。

               这样做的原因有两个:

         1.第一种写法不管该事件有没有响应函数,都会创建一个相应的代理对象。假如一个类中有20个事件,将创建20个代理对象,而这20个代理对象有可能都用不上。

         2.第一种写法编译器将为每一个事件生成Add与Remove方法,这两个方法是线程安全的,因此它包含了一些线程同步的代码。对于根本不需要使用多线程的程序来说,这对性能也是一种损耗。

 

        技巧2.使用静态object代替string类型作为字典主键

               

        在上面的例子中,我们还发现另一个跟我们平常不一样的用法,就是this.Events.AddHandler(EventInit, value);语句中的EventInit属性。我们先看定义

internal static readonly object EventInit;

        它一个简单的object,在这里做主键来使用。我们一般使用字典的时候都习惯用字符串类型作为主键,因此我们会写成this.Events.AddHandler(“EventInit”, value);

        这样写会有两个缺点,第一字符串占内存多,第二容易出错。对于容易出错这一点,有必要展开讲。

        首先,字符串内容不会被编译器检查,非常容易写错,不仅仅是大小写的问题,即使我们把I写成L,编译器也能通过,而有时肉眼很难分辨。当然我们可以定义成常量,但是又回到内存占用的问题上了。

        第二,字符串是一个特殊的类,它的特性其实很多人不是特别了解。比如字符串的驻留,字符串的比较,字符串的哈希。如果集合类把字符串当做一般对象处理,就会出现问题。        

        如果我们使用静态object字段作为主键,则上述两个问题都不会存在。每个对象在内存中的地址都是唯一的,因此用来做主键是非常合适的。

 

        技巧3.使用BitVector代替bool类型字段

 

        在程序中我们经常使用bool类型的字段作为标志,比如Page是否支持视图状态,我们可以定义

public virtual bool EnableViewState{ getset; }

        这样,编译器会自动生成一个bool型的字段。然而我们看实际的源代码:

 

public virtual bool EnableViewState
{
    
get
    {
        
return !this.flags[disableViewState];
    }
    
set
    {
        
this.SetEnableViewStateInternal(value);
    }
}
 
private const int disableViewState = 4;

        关键在于flags对象。该对象是一个SimpleBitVector32类型。使用字典的方式存取标志位,一个SimpleBitVector32对象能保存32个标志位。相当于32个bool型字段。它内部其实也只存了一个int型的字段,但是它使用每一个位作为标志。这样相对于使用bool型字段来说,能大大节省内存。

 

 

 

 

作者: 肖敏 发表于 2011-08-26 11:19 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"