这是我最近的最后一篇关于.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 this[ int 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#region public class NewCollection

/**//*Descrition: */
[Serializable]
public class NewCollection : CollectionBase


{
//Fields
//Properties
public __SomeOjbect__ this[int i_Index]

{

get
{ return this.InnerList[i_Index] as __SomeOjbect__; }

set
{ this.InnerList[i_Index] = value; }
}
//ctor

public NewCollection()
{}
//Methods
public int Add(__SomeOjbect__ i_Object)

{
return this.InnerList.Add(i_Object);
}
public void Remove(__SomeOjbect__ i_Obj)

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

public class Int32CollectionEx
#region public class Int32CollectionEx
[Serializable]
public class Int32Collection : IEnumerable

{
private int[] _InnerArray;
private int _Length;
private int _Capability;
private object _SycObject;
//
public int Length

{

get
{return this._Length;}
}
public int Count

{

get
{return this._Length;}
}
public int Capability

{

get
{return this._Capability;}
}
public int this[ int index ]

{
get

{
if(index<0||index>=this._Length)

{
throw new IndexOutOfRangeException();
}
return this._InnerArray[index];
}
set

{
if(index<0||index>=this._Length)

{
throw new IndexOutOfRangeException();
}
this._InnerArray[index] = value;
}
}
//
public Int32Collection(int i_Capability)

{
this._InnerArray = new int[i_Capability];
this._Capability = i_Capability;
this._Length = 0;
this._SycObject = new object();
}

public Int32Collection() : this(6)

{
}
//
public int Add(int i_Value)

{
lock(this._SycObject)

{
this.CheckCapability();
this._InnerArray[_Length] = i_Value;
this._Length ++;
}
return this._Length;
}

public void Remove(int i_Value)

{
lock(this._SycObject)

{
int i_Index = this.Find(i_Value);
if(i_Index>=0)

{
this.MoveValues_Front(i_Index);
}
this._Length--;
}
}

public void Insert(int i_Index, int i_Value)

{
if(i_Index<0||i_Index>this._Length)

{
throw new IndexOutOfRangeException();
}
lock(this._SycObject)

{
this.CheckCapability();
this.MoveValues_Back(i_Index);
this._InnerArray[i_Index] = i_Value;
this._Length ++;
}
}

private void MoveValues_Front(int i_StartIndex)

{
// if(i_StartIndex<0||i_StartIndex>this._Length)
// {
// throw new IndexOutOfRangeException();
// }
for(int i=i_StartIndex+1; i<this._Length;i++)

{
this._InnerArray[i-1] = this._InnerArray[i];
}
}

private void MoveValues_Back(int i_StartIndex)

{
// if(i_StartIndex<0||i_StartIndex>this._Length)
// {
// throw new IndexOutOfRangeException();
// }
for(int i=this._Length;i>i_StartIndex;i--)

{
this._InnerArray[i] = this._InnerArray[i-1];
}
}

public int Find(int i_Value)

{
for(int i=0; i<this._Length;i++)

{
if(this._InnerArray[i]==i_Value) return i;
}
return -1;
}

public int Find(int i_StartIndex,int i_Value)
![]()