使用后清除对象变量(池)c#

使用后清除对象变量(池)c#,c#,reflection,C#,Reflection,我正在研究一个池算法,它接受一个已分配的对象,并将其循环用于以后的分配。然而,回收物品的一个问题是: someObject obj = pool.alloc(); //gives me a new object if no previous allocations, If an allocation has been recycled, returns a previous allocation obj.someVariable = "foo"; pool.recycle(obj); 上

我正在研究一个池算法,它接受一个已分配的对象,并将其循环用于以后的分配。然而,回收物品的一个问题是:

 someObject obj = pool.alloc(); //gives me a new object if no previous allocations, If an allocation has been recycled, returns a previous allocation
 obj.someVariable = "foo";
 pool.recycle(obj);
上面的代码将获取一个现有的分配并保存它,这样我就不必分配任何额外的ram,以防我有另一个someObject。但是,以下情况会产生一个问题:

 someObject obj = pool.alloc(); //gives me the above allocation
 obj.otherVariable = "bar";
 obj.dump();
因此,我将得到以下结果:

  someVariable = foo
  otherVariable = bar

上述方法产生了一个问题。如果我出于某种原因(或其他人)有一个算法在对象内部不使用某些变量,那么旧的值可能会导致不必要的行为。我已经试了一下,看看是否有什么方法可以再次调用默认构造函数(坏主意),而C#(谢天谢地)似乎不允许这样做。然而,我想知道是否有某种方法可以使用反射来实现这一点?此外,清除对象中的变量是否会破坏避免malloc(新)的目的?换句话说,如果我花时间清理变量,性能增益是否会变得最小?我正在努力自学拼图,所以任何批评和建议都非常感谢

这里有一种看待池的方法:

只有在重用一些复杂的设置工作时,才真正需要使用池,这些工作可以通过检索已存在的对象来避免。例如,最著名的对象池应用程序之一就是“数据库连接”

池对数据库连接(DBConn)有效,因为1)DBConn可以通过连接字符串进行简单标识;2)DBConn的建立需要大量的工作和时间。简单的识别是通过匹配连接字符串来完成的——如果两个连接字符串相同,那么它们建立的连接也应该相同。此外,一旦有了连接字符串,查找服务器地址、打开其套接字、进行身份验证和建立连接可能需要数百毫秒。这意味着池可以很好地用于数据库连接,因为在释放连接时,可以在下次为同一连接字符串请求连接时重用它

NET运行时环境非常擅长快速分配对象并释放它们,这样就不会出现内存问题。如果你所担心的只是内存使用或分配速度,那就不要担心;你不能靠自己把内存归零来提高编译器的性能。但是,如果您的对象有一些复杂、冗长的设置,可以通过从池中检索现有对象来避免,那么您会发现一些好处

另一个很好的例子是视频游戏中的粒子系统。有数百个粒子需要创建、经历生命周期并被销毁,只有在旧粒子死亡后才能创建新粒子。一个典型的粒子系统将创建X个对象作为一个数组,并具有一个Reset()函数,该函数将死掉的对象作为新创建的粒子返回到原始位置。这种方法之所以有效,也是因为粒子可以很容易地识别,并且设置工作(为图形系统提供纹理、放置位置等)

您的应用程序是否既有“微不足道的匹配识别”功能,又有可以避免的冗长的安装过程?如果不是,每次只分配新的对象-我敢打赌你不会看到任何性能下降

编辑:从性能的角度来看,我们来看看这里:

重置变量=O(N)个赋值语句;使用反射可以显著提高这一点

实例化一个新对象=一个malloc调用,一个构造函数调用;复杂性级别取决于构造函数代码和内存碎片

使用反射来重置变量是可行的,但是您必须提前知道赋值的O(N)比malloc和构造函数更快。对于数据库连接,我知道条件已满足;但这对你的游泳池来说是真的吗

编辑:从您下面的评论中,您可能确实发现了一种适合使用池的情况。如果是这样的话,我建议理想的方法是为任何要共享的类创建一个
Reset()
函数。尝试创建一个定义函数的
IPoolable
接口
Reset()
。然后,对于您池中的每个类,定义
Reset()
函数,以便将所有关键变量归零。因为它是编译的,所以不会产生反射开销,并且您可以维护特定于对象的优化,这在动态代码中是不可能的


对于池,将池类定义为
MyPool
;然后,每当检索到以前回收的对象时,您可以在将其交还给调用方之前对其调用
Reset()

您是否有证据表明您需要此池?您可能不想这样做。如果一个变量可以简单地重复使用,编译器/抖动很可能会在你不知道的情况下执行,如果不知道,那么它可能会更昂贵,并且不工作的可能性也更高(同时也会给程序员带来更大的负担,让他们告诉你的应用程序何时完成了每个项目)现在它是一个巨大的ASPX应用程序,可以从数据库中获取数据。很多都不是我的代码,通过使用它,我发现所有的东西都是mallocing对象,通常都是相同类型的对象,通常只是为了很快地丢弃它。一些用户仍然可以,但过了一段时间,它就成了一个负担。另外,不,从使用视频游戏代码来看,GC在管理分配方面是非常糟糕的。对于分配了太多对象的ASPX web服务器,您可能希望开始缓存可能在将来某个位置重新请求的对象,而不是池。尽管垃圾回收器经过了很好的优化,但避免不必要的分配/取消分配将