由于反射的灵活性,总是尝试多使用用于减少代码的开支,但是凡事总是有代价的,反射的效率确实让人汗颜。有文章說测试效率底了250多倍,这个确实有点让人无法忍受了,但是今天在查关于C#函数指针的时候,却让我眼前一亮,事情总是有解决办法的,如果不失反射的灵活又拿回大部分效率,也许大家都会感兴趣的,这里我就来给大家一个测试。
开头的几个测试沿用了网上的几个小测试大家直接看代码
public
class
CTester : ICloneable
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public CTester()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
a = 10;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
public void test1()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
a = (a - 0.0001) * 1.0001;
}
private double a;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public double geta() ...{ return a; }
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
public object Clone()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return this.MemberwiseClone();
}
}
这是主题的测试类,没什么好说的了 开始两个简单测试。
public
void
test1()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DateTime now = DateTime.Now;
for (int i = 0; i < 10000; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < 100; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
CTester aTest = new CTester();
aTest.test1();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TimeSpan spand = DateTime.Now - now;
Console.WriteLine("test1 time past " + spand.ToString());
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
public
void
test2()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DateTime now = DateTime.Now;
Type theTest = Type.GetType("CmdWebBrowse.CTester");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for (int i = 0; i < 10000; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < 100; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
object theobj = theTest.InvokeMember(null, BindingFlags.CreateInstance
, null, null, null);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//theTest.GetMethod("test1").Invoke(theobj,null);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TimeSpan spand = DateTime.Now - now;
Console.WriteLine("test2 只有反射生成 time past " + spand.ToString());
}
为了更容易看到结果我把循环加到了100w次,我的迅驰二笔记本上的时间是
test1 time past 00:00:00.0468750
test2 只有反射生成 time past 00:00:02.2656250
果然差距很大 但是这里就是要来解决这个问题的。
反射生成的速度确实无法让人忍受。但是对于一个对象还有什么办法么?
既然无法直接new 那么我们是否可以拷贝一个?
好的实现克隆,大家也看到了 开头的函数有克隆函数我们来用下
public
void
test5()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
Type theTest = Type.GetType("CmdWebBrowse.CTester");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DateTime now = DateTime.Now;
CTester theobj = theTest.InvokeMember(null, BindingFlags.CreateInstance
, null, null, null) as CTester;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for (int i = 0; i < 10000; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < 100; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
object test = theobj.Clone() ;
theTest.GetMethod("test1").Invoke(test, null);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TimeSpan spand = DateTime.Now - now;
Console.WriteLine("test5 反射一个 克隆对象 执行 反射方法 time past " + spand.ToString());
}
test5 反射一个 克隆对象 执行 反射方法 time past 00:00:04.1093750
看不出来测试时间,由于使用了反射委托 暂时放这里
继续看测试
public
void
test4()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
DateTime now = DateTime.Now;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
Type theTest = Type.GetType("CmdWebBrowse.CTester");
CTester theobj = theTest.InvokeMember(null, BindingFlags.CreateInstance
, null, null, null) as CTester;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for (int i = 0; i < 10000; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < 100; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
CTester test = theobj.Clone() as CTester;
test.test1();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TimeSpan spand = DateTime.Now - now;
Console.WriteLine("test4 克隆反射对象 并且直接执行 time past " + spand.ToString());
}
test4 克隆反射对象 并且直接执行 time past 00:00:00.2031250
看起来让人很满意,但是仅仅是反射一个对象,然后克隆调用一个方法就够了?如果是有公共接口这里就够了,我觉得。但是显然你也许不满足,是的至少我不满足,继续看。
尝试使用一个委托来进行方法调用
public
delegate
void
testdel();
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
public
void
test3()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
Type theTest = Type.GetType("CmdWebBrowse.CTester");
CTester theobj = theTest.InvokeMember(null, BindingFlags.CreateInstance
, null, null, null) as CTester;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DateTime now = DateTime.Now;
testdel method;
for (int i = 0; i < 10000; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < 100; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
method = (testdel)Delegate.CreateDelegate(typeof(testdel), theobj, "test1");
method();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TimeSpan spand = DateTime.Now - now;
Console.WriteLine("test3 委托方法执行 time past " + spand.ToString());
}
test3 委托方法执行 time past 00:00:07.0937500
动态创建委托,速度更无法看了为什么有如此之慢!
public
void
test5()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
Type theTest = Type.GetType("CmdWebBrowse.CTester");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DateTime now = DateTime.Now;
CTester theobj = theTest.InvokeMember(null, BindingFlags.CreateInstance
, null, null, null) as CTester;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for (int i = 0; i < 10000; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < 100; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
object test = theobj.Clone() ;
theTest.GetMethod("test1").Invoke(test, null);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TimeSpan spand = DateTime.Now - now;
Console.WriteLine("test5 反射一个 克隆对象 执行 反射方法 time past " + spand.ToString());
}
test5 反射一个 克隆对象 执行 反射方法 time past 00:00:04.1093750
嗯 不管如何 反射的方法的速度还是太慢
看最后一个测试。。
public
void
test6()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
DateTime now = DateTime.Now;
Type theTest = Type.GetType("CmdWebBrowse.CTester");
CTester theobj = theTest.InvokeMember(null, BindingFlags.CreateInstance
, null, null, null) as CTester;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
testdel method;
method = (testdel)Delegate.CreateDelegate(typeof(testdel), theobj, "test1");
for (int i = 0; i < 10000; i++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < 100; j++)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
method();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TimeSpan spand = DateTime.Now - now;
Console.WriteLine("test6 委托方法重复执行 time past " + spand.ToString());
}
test6 委托方法重复执行 time past 00:00:00.0156250
华丽!太华丽了! 你不觉得么 ?当10万次的时候直接出来一个0 所以我调整到了100万次,你是否感觉到了什么 ?
是否有“啊哈!”这样的感觉? 那么一丝的,一点点的曙光?
是的,至少我感觉到了,今天的测试就到这里,希望大家喜欢,下一篇也许我会为你点亮那片黑暗。
希望大家喜欢:)