值类型的包装和反包装的探讨
时间:2011-03-04 来源:悠竹客
void DoSomething(object par) 而其中的参数par偏偏又常常是值类型,比如int,bool,short之类的类型,在方法过程中你又不得不使用(int)par,(bool)par,(short)par之类的语句来取消包装,这样一来调用该方法时无形中就增加了包装和反包装的资源开销,可以预料得到当你的代码中有许多此类的常用方法签名时,会给你的系统带来巨大的隐形开销.如何避免?这是本文探讨的地方.
1.尽量避免使用object类型的值包装签名,这句话可能大家都会说,其实跟废话一样,能够用实参的类型大家当然都用实参类型签名了.只有没办法使用实参类型签名的地方才会使用object来签名.比如很多地方使用的数据属性
object this[string fieldname]{get;set;},象这样的数据行中数据字段值获取和设置的属性应该在很多应用都用到,而且是很常用的.
2.避免包装和取消包装的的方法:
象上例中的属性的值基本是值类型,如何避免包装和取消包装呢,我有个思路,那就是建一个象c++中联合结构一样的结构,里头存储的数据每个时刻仅有一中有效,同时它又能在任何时刻给它辅值成其它类型的值,该结构就象下面这样:
首先定义一个数据类型枚举
public enum SimpleValueType : byte { /// <summary> /// 未知 /// </summary> Unkown = 0, /// <summary> /// Bool类型 /// </summary> Boolean = 1, /// <summary> /// byte /// </summary> Byte = 2, /// <summary> /// sbyte /// </summary> SByte = 3, /// <summary> /// short /// </summary> Int16 = 4, /// <summary> /// int /// </summary> Int32 = 5, /// <summary> /// long /// </summary> Int64 = 6, /// <summary> /// ushort /// </summary> UInt16 = 7, /// <summary> /// uint /// </summary> UInt32 = 8, /// <summary> /// ulong /// </summary> UInt64 = 9, /// <summary> /// float /// </summary> Single = 10, /// <summary> /// double /// </summary> Double = 11, /// <summary> /// decimal /// </summary> Decimal = 12, /// <summary> /// DateTime /// </summary> DateTime = 13, /// <summary> /// 枚举类型 /// </summary> Enum = 14, /// <summary> /// DbNull /// </summary> DbNull = 15, /// <summary> /// char /// </summary> Char = 16, /// <summary> /// guid /// </summary> Guid = 17, /// <summary> /// TimeSpan /// </summary> TimeSpan = 18, /// <summary> /// point /// </summary> Point = 100, /// <summary> /// size /// </summary> Size = 101, /// <summary> /// Color /// </summary> Color = 102, /// <summary> /// UnionSimpleValueTypeValue /// </summary> UnionSimpleValueTypeValue = 103, /// <summary> /// char[] /// </summary> Chars = 251, /// <summary> /// string /// </summary> String = 252, /// <summary> /// 二进制对象数据(byte[]) /// </summary> Bytes = 253, /// <summary> /// Type /// </summary> Type = 254, /// <summary> /// 未知的对象类型 /// </summary> UnkownObject = 255 }
再定义一个联合结构
[StructLayout(LayoutKind.Explicit)] internal struct UnionValueType { [FieldOffset(0)] internal SimpleValueType p_Flag; [FieldOffset(1)] internal long p_Long; [FieldOffset(1)] internal ulong p_ULong; [FieldOffset(1)] internal int p_Int; [FieldOffset(1)] internal uint p_UInt; [FieldOffset(1)] internal short p_Short; [FieldOffset(1)] internal ushort p_UShort; [FieldOffset(1)] internal byte p_Byte; [FieldOffset(1)] internal sbyte p_SByte; [FieldOffset(1)] internal bool p_Bool; [FieldOffset(1)] internal Guid p_Guid; [FieldOffset(1)] internal decimal p_Decimal; [FieldOffset(1)] internal DateTime p_Date; [FieldOffset(1)] internal float p_Float; [FieldOffset(1)] internal char p_Char; [FieldOffset(9)] internal long p_NL; [FieldOffset(1)] internal byte p_C1; [FieldOffset(2)] internal byte p_C2; [FieldOffset(3)] internal byte p_C3; [FieldOffset(4)] internal byte p_C4; }
这样上面的联合结构就能代表多种数据类型了
那上述的属性就可以这样定义了
UnionValueType this[string fieldname]{get;set;}
这样的定义方式就没有了包装了取消包装的开销了,当然了,为了使该结构有实用性,你还得在结构中定义诸如此类的运算符:
bool operator ==,bool operator !=,bool operator >,bool operator <,bool operator =>,bool operator <=
explicit operator int(UnionValueType v),implicit operator UnionValueType(int v)等等运算符
水平有限,请大家探讨一下,看看还有其它方法不?