Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 困惑的CA1063错了吗?GC.1(本)_C#_.net_Garbage Collection - Fatal编程技术网

C# 困惑的CA1063错了吗?GC.1(本)

C# 困惑的CA1063错了吗?GC.1(本),c#,.net,garbage-collection,C#,.net,Garbage Collection,我有一个简单的类MyDataClass,其中包含一个实现IDisposable的成员(obj): public class MyDataClass : IDisposable { private DisposableObject obj; private List<string> list; private int c; public MyDataClass() { obj = new DisposableObject();

我有一个简单的类MyDataClass,其中包含一个实现IDisposable的成员(obj):

public class MyDataClass : IDisposable
{
    private DisposableObject obj;
    private List<string> list;
    private int c;

    public MyDataClass()
    {
        obj = new DisposableObject();
        list = new List<string>();
        c = 114;
    }

    public void Dispose()
    {
        obj.Dispose();
    }
}

public class DisposableObject : IDisposable
{
    public void Dispose()
    {
        // Free resource
        Console.WriteLine("Dispose DisposableObject");
    }
}
公共类MyDataClass:IDisposable
{
私人可处分物;
私人名单;
私人INTC;
公共MyDataClass()
{
obj=新的可处置对象();
列表=新列表();
c=114;
}
公共空间处置()
{
obj.Dispose();
}
}
公共类可处置对象:IDisposable
{
公共空间处置()
{
//免费资源
Console.WriteLine(“处置可处置对象”);
}
}
当我运行代码分析时,我得到CA1063警告,它显示我应该在MyDataClass实现中的Dispose()方法中调用GC.SuppressFinalize()方法

我真的对CA1063警告感到困惑。因为据我所知,我应该调用GC.SuppressFinalize()向垃圾收集器指示:

“嘿,GC,不要担心这个物体,因为我已经为你做了所有的清洁工作!”

所以请确认我是否错了。如果我将添加GC.SuppressFinalize()我将去掉CA1063,但这将导致GC不会清理我的对象。因此,我将有一个内存泄漏,因为其他类成员(托管代码)将不会被清理

如果我将添加
GC.SuppressFinalize()
,我将摆脱CA1063 但这将导致GC无法清理我的对象

不,您的对象仍将被收集

“嘿,GC,不要担心这个物体,因为我已经为你做了所有的清洁工作!”

您实际上只是说:不要担心这个对象的终结器(析构函数)。如果有


这就是代码分析出错的地方:您的类确实有一个IDisposable.Dispose()方法,但它没有析构函数。因此,警告毫无意义,保护过度,触发原因错误。禁用或忽略它

方法
GC.SuppressFinalize()
指示VM不要运行终结器。这是C#中看起来很滑稽的方法:

~MyDataClass()


要删除警告,您需要密封您的类,或者实现完整的。

我感觉您仍然感到困惑,尽管已经接受了答案。让我解释一下:

垃圾收集器(GC)的任务是从内存中删除任何无法访问的对象

可达性 对象
A
仅当存在从任何GC根到该对象的任何引用链时才可访问。根的示例包括堆栈和任何静态字段。因此,要确定
A
是否可访问,GC所要做的就是在堆栈上找到一个引用对象的引用,该引用对象有一个引用对象的引用。。。指的是对象
A
。如果找不到这样的链,则无法访问对象
a
。1

因此,一旦GC确定
A
不可访问,它就会希望将其从内存中删除。 但是,在此之前,GC检查
A
是否有必须运行的终结器(
~A
)。如果没有,它将从内存中删除
A
,并完成GC

定稿 但是,如果
A
具有必须运行的终结器,则在终结器完成之前,它无法从内存中删除对象。因此,它向终结器队列中添加了对
a
的引用,并且还没有从内存中删除对象。现在,垃圾回收器已使用
A
完成。但是,当GC再次运行时,它将再次尝试确定
A
是否可访问。幸运的是,终结器队列也是垃圾收集器的根之一,因此它确定存在从终结器队列到
a
的引用,因此
a
是可访问的,并且不会再次从内存中删除

随之而来的是终结器线程,该线程定期检查终结器队列中是否有任何对象。如果有,它将选择一个并运行其终结器方法。最终,终结器线程将运行
A
的终结器。完成此操作后,将从终结器队列中删除对
A
的引用

清理 然后,一段时间后,垃圾收集器再次运行,并尝试再次确定
A
是否可访问。由于它现在不在任何地方引用,甚至不从终结器队列引用,
A
无法访问。GC从内存中删除
A


您可以看到,通常GC可以在检测到无法访问的对象的同一个收集周期中删除这些对象,但是当一个对象有一个需要运行的终结器时,收集该对象可能需要多个周期。因此,CA1063建议您将
GC.SuppressFinalize()
放在
Dispose
方法中,让GC知道在将对象从内存中删除之前不需要完成对象。因此,对象最终总是从内存中删除

请注意,如果没有终结器,则不必添加
GC.SuppressFinalize()
,因此在这方面,CA1063警告有点多余

可以找到关于垃圾收集器的更深入的信息


1)可达性是在处理引用后将引用设置为
null
的常见原因。这使得引用的对象很可能无法访问,因此将删除候选对象

2)通过使用终结器从另一个可访问对象或根(例如静态字段)添加对
A
的引用,可以(但不建议)恢复
A
。这会使
A
再次可访问,垃圾收集器不会将其删除。然而,它的终结器w