我有一个类实例,它实现了IDisposable接口,如下所示。
finally
{
if (inst1 != null)
{
inst1.Dispose();
inst1 = null;
}
if (inst2 != null)
{
inst2.Dispose();
inst2 = null;
}
if (inst3 != null)
{
inst3.Dispose();
inst3 = null;
}
}
现在在实际代码中我有几个实例的实例需要在下面的finally块中处理
static void DisposeInstance(params Instance[] instances)
{
for (int i = 0; i < instances.Length; i++)
{
if (instances[i] != null)
{
instances[i].Dispose();
instances[i] = null;
}
}
}
所以每当我想要Dispose时,我必须为每个对象编写上面的行。
我觉得我可以使用'params'关键字减少号码。 LOC(代码行)如下所示
DisposeInstance(inst1, inst2, inst3);
并在单个镜头中传递实例,如
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/txtNumber"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:text="@string/txtNumber" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/txtName"
android:id="@+id/txtName"
android:layout_gravity="top|bottom"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/txtScore"
android:id="@+id/txtScore"
android:layout_weight="1" />
</LinearLayout>
但是上面的函数只会处理Instance的本地副本,并且不会完全处理实际的对象(实例)。
所以我的问题是,如果有任何方法可以实现我的目标,即一次性处理对象并减少LOC。
我也可以使用'ref'关键字和'params'(我知道这会产生编译错误),但是不知怎的混合这两个以获得结果?
提前致谢!
答案 0 :(得分:3)
您不需要将对象设置为null,使用C#6可以使用Null-Propagation语法:
inst1?.Dispose();
inst2?.Dispose();
inst3?.Dispose();
这大大降低了噪音。
答案 1 :(得分:0)
您可以将列表发送到您的方法
static void DisposeInstancies(List<Instance> instances)
{
for (int i = 0; i < instances.Length; i++)
{
if (instances[i] != null)
{
instances[i].Dispose();
instances[i] = null;
}
}
}
所以:
DisposeInstancies(new List<Instance> {inst1, inst2, inst3});
答案 2 :(得分:0)
您可以尝试使用using statement自动处理对象。像这样:
using (MyClass inst1 = new MyClass())
using (MyClass1 inst2 = new MyClass1())
using (MyClass2 inst3 = new MyClass2())
{
// code
}
using语句允许程序员指定对象的时间 使用资源应该释放它们。提供给使用的对象 语句必须实现IDisposable接口。这个界面 提供Dispose方法,该方法应该释放对象 资源。
答案 3 :(得分:0)
但是上面的函数只会处理Instance的本地副本,并且不会完全处理实际的对象(实例)。
它处理对象(或至少调用方法Dispose()
),但它不在调用者范围内将引用设置为null。实际上,只有复制的引用值在DisposeInstance
范围内设置为null。
你真的需要将它设置为null吗?如果您的目标是避免因多次调用Dispose()
而导致的错误,那么您应该使用布尔来控制状态:
private bool hasBeenDisposed ;
public void Dispose()
{
if (!hasBeenDisposed)
{
DisposeInstance(inst1, inst2, inst3);
hasBeenDisposed = true ;
}
}
此外,您应将DisposeInstance args更改为IDisposable []
以获得可重用性和可读性。
static void DisposeInstance(params IDisposable [] instances)
{
for (int i = 0; i < instances.Length; i++)
{
if (instances[i] != null)
{
instances[i].Dispose();
instances[i] = null;
}
}
}
答案 4 :(得分:0)
关于处置的一点点。
处理对象时,清除大型内容对象的对象。您只需孤立您正在处理的对象的内容,以便GC可以自由选择它们。
如果你想要在IDIposposable实现的对象中没有任何大对象或数组,那么你真的不需要处理它。如果你需要内存中的空间,那么只需将其置空以强制它超出范围并进入GC。
(这里有一个角落的情况,GC停止你的程序收集,所以如果你有很多小物件,那么当你有“时间”时处理它们是一个很好的方法去处理它们后记得抑制GC)
如开发人员所做的那样,处置是一种判断。在大多数情况下,您并不真正需要它,在多种情况下,处理包含较大数组/集合的对象很不错。
因此,对于您的问题,我建议您在完成课程后处理,而不是等到“范围”结束时,或者将它们放在列表中并稍后处理。
Queue<IDisposable> toDispose = new Queue<IDisposable>();
private void DisposeObjects(){
while(toDispose.Any()){
toDispose.Dequeue()?.Dispose();
}
}