表達式樹淺拷貝對象、反射淺拷貝對象對比手寫的Copy方法100萬次耗時對比(CPU是 i7 - 4710MQ)
static void Main(string[] args)
{
var value = new TestClass
{
Age = 18,
Name = "張三",
Sex = Gender.Man
};
Console.WriteLine("-------手寫代碼------");
for (int j = 0; j < 5; j++)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++)
{
var copyValue = Copy(value);//手寫的Copy
}
sw.Stop();
Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
}
Console.WriteLine("-------表達式樹------");
for (int j = 0; j < 5; j++)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++)
{
var copyValue = ShallowCopy<TestClass>.Copy(value);//表達式樹實現的Copy【程序啓動的第一次Copy需要編譯會慢一點】
}
sw.Stop();
Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
}
Console.WriteLine("-------反射生成------");
for (int j = 0; j < 5; j++)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000; i++)
{
var copyValue = ShallowCopyReflect<TestClass>.Copy(value);//反射實現Copy
}
sw.Stop();
Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
}
}
public static TestClass Copy(TestClass value)
{
return new TestClass
{
Age = value.Age,
Name = value.Name,
Sex = value.Sex
};
}
public class TestClass
{
public int Age { get; set; }
public string Name { get; set; }
public Gender Sex { get; set; }
}
public enum Gender
{
Man = 0,
Woman = 1
}
耗時:↓
-------手寫代碼------
42.7358ms
36.8807ms
35.0374ms
34.8473ms
35.1947ms
-------表達式樹------
132.8095ms
132.7188ms
124.1226ms
124.3291ms
124.0487ms
-------反射生成------
2501.8246ms
2357.8119ms
2353.0715ms
2351.2028ms
2341.6874ms
表達式樹Copy類
/// <summary>
/// 淺拷貝類
/// </summary>
/// <typeparam name="T">拷貝的類型</typeparam>
public static class ShallowCopy<T> where T : new()
{
/// <summary>
/// 淺拷貝委託對象樹
/// </summary>
private static readonly Func<T, T> CopyFunc;
static ShallowCopy()
{
var value = Expression.Parameter(typeof(T));
var copyValue = Expression.New(typeof(T));
var bindProValues = typeof(T).GetProperties().Where(w => w.CanWrite && w.CanRead).Select(pro => Expression.Bind(pro, Expression.Property(value, pro))).ToArray();
var initProValue = Expression.MemberInit(copyValue, bindProValues);
var lambda = Expression.Lambda<Func<T, T>>(initProValue, new[] { value });
CopyFunc = lambda.Compile();
}
/// <summary>
/// 拷貝方法
/// </summary>
/// <param name="value">需要被拷貝的值</param>
/// <returns>拷貝的值</returns>
public static T Copy(T value)
{
if (value == null) return default(T);
return CopyFunc(value);
}
}
反射實現的Copy類
/// <summary>
/// 淺拷貝類反射實現
/// </summary>
/// <typeparam name="T">拷貝的類型</typeparam>
public static class ShallowCopyReflect<T> where T : new()
{
private readonly static PropertyInfo[] Properties;
private readonly static ConstructorInfo Constructor;
static ShallowCopyReflect()
{
Properties = typeof(T).GetProperties().Where(w => w.CanWrite && w.CanRead).ToArray();
Constructor = typeof(T).GetConstructor(new Type[0]);
}
/// <summary>
/// 拷貝方法
/// </summary>
/// <param name="value">需要被拷貝的值</param>
/// <returns>拷貝的值</returns>
public static T Copy(T value)
{
if (value == null) return default(T);
var copyValue = Constructor.Invoke(null);
foreach (var property in Properties)
{
property.SetValue(copyValue, property.GetValue(value));
}
return (T)copyValue;
}
}