public class oddsRecoder : ICloneable, IDisposable
{
private bool bool_0;
private string _guid = string.Empty;
public IDictionary<string, IDictionary<string, IDictionary<string, string>>> dictionary = new Dictionary<string, IDictionary<string, IDictionary<string, string>>>();
private IDictionary<string, dic_PlayData> DataCollection = new Dictionary<string, dic_PlayData>(); public object Clone()
{
try
{
MemoryStream serializationStream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(serializationStream, this);
serializationStream.Position = 0L;
Thread.GetDomain().AssemblyResolve += new ResolveEventHandler(this.m0000ca);
object obj2 = formatter.Deserialize(serializationStream);
Thread.GetDomain().AssemblyResolve -= new ResolveEventHandler(this.m0000ca);
return obj2;
}
catch (Exception ex)
{
Console.Write(ex.Message); Log.a(ex, 1000);
}
return null;
} public void Dispose()
{
this.m000075(true);
GC.SuppressFinalize(this);
}
一个存放数据的类,结果发现在复制的时候相当费时,有没有更高效的方法,这里的dic_PlayData类,也有很多idictionary、string、datetime等成员,一个一个复制可能比较麻烦,大家是怎么做的呢?
http://blog.nuclex-games.com/mono-dotnet/fast-deep-cloning/
是啊,可是这样真的效率很差啊,有没有更好的办法呢
{
public virtual Team Clone2()
{
Team c = new Team();
c.Time = this.Time;
c.RaceName =this.RaceName;
c.Name = this.Name;
c.RightName = this.RightName;
c.Score = this.Score;
c.VSName= this.VSName;
return c;
}
} public class ChildrenTeam
{
public override ChildrenTeam Clone2()
{
ChildrenTeam c = new ChildrenTeam();
c.Time = this.Time;
c.RaceName =this.RaceName;
c.Name = this.Name;
c.RightName = this.RightName;
c.Score = this.Score;
c.VSName= this.VSName;
//基类特有的变量
c.ID=this.ID;
return c;
}
}自身拷贝算了,继承类的COLNE是不是写的太麻烦了点,如果有好几个继承类的话,每个都得改,这样“ ChildrenTeam c = base.Clone2() as ChildrenTeam ; c._ID=this.ID”貌似可以解决,但面临装箱拆箱的效率问题,大家有没有更好的写法?
这个国际用的比较多。据国外的一个测试效率是最高的。
但不知道是不是和二楼给出是不是同一个。
用Emit,效率可以比序列化提高一百倍左右,信不信由你。
核心代码:
static List<FieldInfo> GetSettableFields(Type t)
{
return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToList();
}
//暂时只能支持简单类的克隆,也就是类的内部只有基础类型。
static Func<object, object> CreateCloneMethod(Type type)
{
var fields = GetSettableFields(type);
var dm = new DynamicMethod(string.Format("Clone{0}", Guid.NewGuid()), typeof(object), new[] { typeof(object) }, true);
var il = dm.GetILGenerator();
il.DeclareLocal(type);
il.DeclareLocal(type);
il.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, type);
il.Emit(OpCodes.Stloc_0);
foreach (var field in fields)
{
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldfld, field);
il.Emit(OpCodes.Stfld, field);
}
il.Emit(OpCodes.Ret); return (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>));
}
验证(如果不是深度复制,而是引用赋值,这里面if判断将会相等而不输出u2的内容): Func<object, object> clone = CreateCloneMethod(typeof(DT_USER));
DT_USER u1 = new DT_USER() { USER_NO = 1, USER_LNAME = "001" };
DT_USER u2 = clone(u1) as DT_USER;
if (u1 != u2)
{
Console.WriteLine(u2.USER_LNAME);
}
DT_USER u1 = new DT_USER() { USER_NO = 1, USER_LNAME = "001" };
DT_USER u2 = null;Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
u2 = u1.Clone();
}
sw.Stop();
Console.WriteLine("手写代码克隆执行10万次所用时间:" + sw.ElapsedMilliseconds + "毫秒");sw.Restart();
for (int i = 0; i < 100000; i++)
{
u2 = clone(u1) as DT_USER;
}
sw.Stop();
Console.WriteLine("Emit执行10万次所用时间:" + sw.ElapsedMilliseconds + "毫秒");sw.Restart();
for (int i = 0; i < 100000; i++)
{
MemoryStream serializationStream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(serializationStream, u1);
serializationStream.Position = 0;
u2 = formatter.Deserialize(serializationStream) as DT_USER;
serializationStream.Close();
}
sw.Stop();
Console.WriteLine("序列化方式执行10万次所用时间:" + sw.ElapsedMilliseconds + "毫秒");输出结果为:
手写代码克隆执行10万次所用时间:28毫秒
Emit执行10万次所用时间:18毫秒
序列化方式执行10万次所用时间:6185毫秒这里要注意:那个CreateCloneMethod创建的委托必须缓存后才能重复使用,缓存的方式很简单,定义一个全局静态字典Dictionary<Type,Func<object, object>>,由于每个具体的Type只能对应一个Clone委托,那么你的程序运行中只要创建一次Clone委托,就可以重复使用了,执行效率最高。
对于你的这个测试,我不是很理解,因为硬编码在执行一次就转化为MSIL,跟EMIT一样了,双方应该是一样的吧,我查了一下,貌似整体EMIT的性能接近硬编码,但要差,可能只有在赋值方面,才可以超过,但也是差不多了,他并不能大幅提高性能。
我的这个类的CLOnE,包括泛型字典,有EMIT有解吗?本想结贴,还没有跟你聊够呢,哈哈~~
另外你似乎不懂什么叫“运行时”,那个EMIT创建的方法是“运行时”方法,不同于直接C#编写的方法,“运行时”方法是不能被编译器语法检测的,出错也只能在运行时被发现,编译的时候根本就没那个方法存在,自然无法检测是否有错误。“运行时”创建方法最大的好处是可以结合当时的实际情况来创建,条件变了,创建的方法就不同,这里所谓的条件改变,就是要Clone的类型对象改变。这样就达到了一次编程,多处使用了。否则你要为每个类创建的时候都写一遍Clone方法,内置类型还无法直接编写。