Wu.Country@侠缘

勤学似春起之苗,不见其增,日有所长; 辍学如磨刀之石,不见其损,日所有亏!

导航

自己实现Int32Collection(.Net 1.1),以及效率问题的体会

这是我最近的最后一篇关于.Net技术的随笔了,一方面把这个集合的实现写一下,另一方面也写一些关于.Net想法与总结,以后就很少在这里更新随笔了。

首先,我并不太在意是用1.1还是2.0或者3.5版本的.Net Framework,因为最后编译成IL语言后,没有什么区别。太多的改变只是CS编译器上的修改,让C#的功能强大了一些,让语言更简洁,也让开发更快了。我不想说太多的细节,据我所了解,C#2.0的一些改进都可以用1.1做一些小的技巧来实现。(不要让这些技巧成了MS的专利)

一个重大的改进就是强类型的集合。1.1里的通用集合类型ArrayList可以说是万能的,然而带来的后果就是效率问题。.Net性能的开销很多就是在Boxing和Unboxing,以及类型转换上。然而这些,有很多人不明白,在自己的代码里写了N多的Boxing和Unboxing还不知道,然后就说.Net效率低下。其实效率问题90%是程序员自己的问题。这个就不多说了。

2.0的泛型对集合中元素的数据类型做了检测,这样,就省去了类型转化的开销。而且,对于值类型的集合,它也不再是封装成Object以后再放到集合里,这样就省去了Boxing和Unboxing的开销。可以说是一个不小的改进。这里我给出一个1.1下Int32集合的两种写法,比较一下就会让很多人明白一些关于性能与效率的问题了。

这是MSDN里的一段示例代码,告诉我们如何自己写一个强类型的集合,这里以int32为例:

    [Serializable]
    
public class Int32Collection : CollectionBase  
    
{
        
public Int32 thisint index ]  
        
{
            
get  
            
{
                
return( (Int32) List[index] );
            }

            
set  
            
{
                List[index] 
= value;
            }

        }


        
public int Add( Int32 value )  
        
{
            
return( List.Add( value ) );
        }


        
public int IndexOf( Int32 value )  
        
{
            
return( List.IndexOf( value ) );
        }


        
public void Insert( int index, Int32 value )  
        
{
            List.Insert( index, value );
        }


        
public void Remove( Int32 value )  
        
{
            List.Remove( value );
        }


        
public bool Contains( Int32 value )  
        
{
            
// If value is not of type Int32, this will return false.
            return( List.Contains( value ) );
        }


        
protected override void OnInsert( int index, Object value )  
        
{
            
if ( value.GetType() != Type.GetType("System.Int32") )
                
throw new ArgumentException( "value must be of type Int32.""value" );
        }


        
protected override void OnRemove( int index, Object value )  
        
{
            
if ( value.GetType() != Type.GetType("System.Int32") )
                
throw new ArgumentException( "value must be of type Int32.""value" );
        }


        
protected override void OnSet( int index, Object oldValue, Object newValue )  
        
{
            
if ( newValue.GetType() != Type.GetType("System.Int32") )
                
throw new ArgumentException( "newValue must be of type Int32.""newValue" );
        }


        
protected override void OnValidate( Object value )  
        
{
            
if ( value.GetType() != Type.GetType("System.Int32") )
                
throw new ArgumentException( "value must be of type Int32." );
        }

    }
    
这是通用的,以致于我们可以写一个模板:
public class NewCollection
确实,我在自己的项目中经常这样用,特别是那个集合模板。然而它的几个缺点就如我前面说的。其实我们可以手动的改进一下,省掉Boxing和Unboxing以及类型转化。
这里我又写了一个简单的Int32Collection类,它就省掉Boxing和Unboxing以及类型转化:
#    if Int32CollectionEx
    
public class Int32CollectionEx

#    endif

    
public class Int32Enumerator
这些代码算是学习一下吧,在2.0里就有了很大的改进,不用我们再花大力气来做这些事情了,而且这是机械式的代码。谁也不想为了一个集合的效率要写这么多代码,而且简单的几行也可以实现同样的功能时,很多人就选择了前者。(把这样的工作交给编译器来做确实是很明智的事。)

选哪方法并没有太大关系,在我的测试中,发现它们的性能开销在一般的应用中, 人根本感觉不到。然而,我觉得做为一个.Net开发人员,特别是注意细节的开发人员,应该时刻注意这些问题,不至于自己写出大量的低效率代码还不知道。

好了,这个讨论就这些!

posted on 2007-11-29 09:13  Wu.Country@侠缘  阅读(757)  评论(2编辑  收藏  举报