Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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# 正确实现IDisposable_C#_.net_Memory Management_Memory Leaks_Garbage Collection - Fatal编程技术网

C# 正确实现IDisposable

C# 正确实现IDisposable,c#,.net,memory-management,memory-leaks,garbage-collection,C#,.net,Memory Management,Memory Leaks,Garbage Collection,在我的类中,我实现了IDisposable,如下所示: public class User : IDisposable { public int id { get; protected set; } public string name { get; protected set; } public string pass { get; protected set; } public User(int UserID) { id = User

在我的类中,我实现了
IDisposable
,如下所示:

public class User : IDisposable
{
    public int id { get; protected set; }
    public string name { get; protected set; }
    public string pass { get; protected set; }

    public User(int UserID)
    {
        id = UserID;
    }
    public User(string Username, string Password)
    {
        name = Username;
        pass = Password;
    }

    // Other functions go here...

    public void Dispose()
    {
        // Clear all property values that maybe have been set
        // when the class was instantiated
        id = 0;
        name = String.Empty;
        pass = String.Empty;
    }
}
在VS2012中,我的代码分析说要正确实现IDisposable,但我不确定我在这里做错了什么。
全文如下:

public class User : IDisposable
{
    public int id { get; protected set; }
    public string name { get; protected set; }
    public string pass { get; protected set; }

    public User(int UserID)
    {
        id = UserID;
    }
    public User(string Username, string Password)
    {
        name = Username;
        pass = Password;
    }

    // Other functions go here...

    public void Dispose()
    {
        // Clear all property values that maybe have been set
        // when the class was instantiated
        id = 0;
        name = String.Empty;
        pass = String.Empty;
    }
}
CA1063 Implement IDisposable在“User”上正确提供可重写的Dispose(bool)实现,或将类型标记为sealed。调用Dispose(false)应该只清理本机资源。调用Dispose(true)应该清除托管资源和本机资源。stman User.cs 10

供参考:

我已经看完了这一页,但恐怕我真的不明白这里需要做什么


如果有人能用更通俗的语言解释问题所在和/或应该如何实现
IDisposable
,那将非常有帮助

IDisposable
的存在为您提供了一种清理非托管资源的方法,这些资源不会被垃圾收集器自动清理


您正在“清理”的所有资源都是托管资源,因此您的
Dispose
方法一事无成。您的类根本不应该实现
IDisposable
。垃圾收集器将自行处理所有这些字段。

首先,您不需要“清理”字符串和
int
s-垃圾收集器将自动处理这些字段。在
Dispose
中唯一需要清理的是实现
IDisposable
的非托管资源或托管资源

但是,假设这只是一个学习练习,建议实施
IDisposable
的方法是添加一个“安全锁销”,以确保任何资源不会被两次处置:

public void Dispose()
{
    Dispose(true);

    // Use SupressFinalize in case a subclass 
    // of this type implements a finalizer.
    GC.SuppressFinalize(this);   
}
protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing) 
        {
            // Clear all property values that maybe have been set
            // when the class was instantiated
            id = 0;
            name = String.Empty;
            pass = String.Empty;
        }

        // Indicate that the instance has been disposed.
        _disposed = true;   
    }
}

您需要像这样使用一次性模式

private bool _disposed = false;

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {
            // Dispose any managed objects
            // ...
        }

        // Now disposed of any unmanaged objects
        // ...

        _disposed = true;
    }
}

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);  
}

// Destructor
~YourClassName()
{
    Dispose(false);
}

这将是正确的实现,尽管我在您发布的代码中没有看到任何需要处理的内容。只有在以下情况下,才需要实现
IDisposable

  • 您拥有非托管资源
  • 你会保留那些本身就是一次性的东西
  • 您发布的代码中没有任何内容需要处理

    public class User : IDisposable
    {
        public int id { get; protected set; }
        public string name { get; protected set; }
        public string pass { get; protected set; }
    
        public User(int userID)
        {
            id = userID;
        }
        public User(string Username, string Password)
        {
            name = Username;
            pass = Password;
        }
    
        // Other functions go here...
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (disposing) 
            {
                // free managed resources
            }
            // free native resources if there are any.
        }
    }
    

    由于类不获取任何非托管资源(文件、数据库连接等),因此您无需将
    User
    类设置为
    IDisposable
    。通常,我们把班级标记为
    IDisposable
    如果它们至少有一个
    IDisposable
    字段或/和属性。 在实施
    IDisposable
    时,最好按照微软的典型方案:

    public class User: IDisposable {
      ...
      protected virtual void Dispose(Boolean disposing) {
        if (disposing) {
          // There's no need to set zero empty values to fields 
          // id = 0;
          // name = String.Empty;
          // pass = String.Empty;
    
          //TODO: free your true resources here (usually IDisposable fields)
        }
      }
    
      public void Dispose() {
        Dispose(true);
    
        GC.SuppressFinalize(this);
      } 
    }
    

    Idisposable是在需要确定(确认)垃圾收集时实现的

    class Users : IDisposable
        {
            ~Users()
            {
                Dispose(false);
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
                // This method will remove current object from garbage collector's queue 
                // and stop calling finilize method twice 
            }    
    
            public void Dispose(bool disposer)
            {
                if (disposer)
                {
                    // dispose the managed objects
                }
                // dispose the unmanaged objects
            }
        }
    
    创建和使用Users类时,请使用“using”块以避免显式调用dispose方法:

    using (Users _user = new Users())
                {
                    // do user related work
                }
    

    using block end created Users对象将通过dispose方法的隐式调用进行处置。

    以下示例显示了实现
    IDisposable
    接口的一般最佳实践

    请记住,只有在类中有非托管资源时,才需要析构函数(终结器)。如果添加析构函数,则应在Dispose中禁止终结,否则将导致对象在内存中驻留两个垃圾周期(注意:)。下面的例子详细说明以上所有内容

    public class DisposeExample
    {
        // A base class that implements IDisposable. 
        // By implementing IDisposable, you are announcing that 
        // instances of this type allocate scarce resources. 
        public class MyResource: IDisposable
        {
            // Pointer to an external unmanaged resource. 
            private IntPtr handle;
            // Other managed resource this class uses. 
            private Component component = new Component();
            // Track whether Dispose has been called. 
            private bool disposed = false;
    
            // The class constructor. 
            public MyResource(IntPtr handle)
            {
                this.handle = handle;
            }
    
            // Implement IDisposable. 
            // Do not make this method virtual. 
            // A derived class should not be able to override this method. 
            public void Dispose()
            {
                Dispose(true);
                // This object will be cleaned up by the Dispose method. 
                // Therefore, you should call GC.SupressFinalize to 
                // take this object off the finalization queue 
                // and prevent finalization code for this object 
                // from executing a second time.
                GC.SuppressFinalize(this);
            }
    
            // Dispose(bool disposing) executes in two distinct scenarios. 
            // If disposing equals true, the method has been called directly 
            // or indirectly by a user's code. Managed and unmanaged resources 
            // can be disposed. 
            // If disposing equals false, the method has been called by the 
            // runtime from inside the finalizer and you should not reference 
            // other objects. Only unmanaged resources can be disposed. 
            protected virtual void Dispose(bool disposing)
            {
                // Check to see if Dispose has already been called. 
                if(!this.disposed)
                {
                    // If disposing equals true, dispose all managed 
                    // and unmanaged resources. 
                    if(disposing)
                    {
                        // Dispose managed resources.
                        component.Dispose();
                    }
    
                    // Call the appropriate methods to clean up 
                    // unmanaged resources here. 
                    // If disposing is false, 
                    // only the following code is executed.
                    CloseHandle(handle);
                    handle = IntPtr.Zero;
    
                    // Note disposing has been done.
                    disposed = true;
    
                }
            }
    
            // Use interop to call the method necessary 
            // to clean up the unmanaged resource.
            [System.Runtime.InteropServices.DllImport("Kernel32")]
            private extern static Boolean CloseHandle(IntPtr handle);
    
            // Use C# destructor syntax for finalization code. 
            // This destructor will run only if the Dispose method 
            // does not get called. 
            // It gives your base class the opportunity to finalize. 
            // Do not provide destructors in types derived from this class.
            ~MyResource()
            {
                // Do not re-create Dispose clean-up code here. 
                // Calling Dispose(false) is optimal in terms of 
                // readability and maintainability.
                Dispose(false);
            }
        }
        public static void Main()
        {
            // Insert code here to create 
            // and use the MyResource object.
        }
    }
    

    我看到很多Microsoft Dispose模式的例子,它实际上是一种反模式。正如许多人指出的,问题中的代码根本不需要IDisposable。但是如果您想在哪里实现它,请不要使用Microsoft模式。更好的答案是遵循本文中的建议:


    唯一可能有用的另一件事是抑制代码分析警告

    这是
    Dispose
    中的所有代码吗?您应该使用/调查
    IDisposable模式。我相信你很快就会得到很多详细的答案,但基本上它涉及到
    GC.superssFinalize()
    和析构函数等。你应该实现Dispose()方法来调用类中任何成员的Dispose()方法。这些成员都没有。因此,不应实现IDisposable。重置属性值是毫无意义的。如果要处置非托管资源(包括已包装的非托管资源(
    SqlConnection
    FileStream
    等),则只需实现
    idisable
    )。如果您只有这里这样的托管资源,您不应该也不应该实现
    IDisposable
    。这是代码分析的一个主要问题。它非常擅长检查愚蠢的小规则,但不擅长检查概念错误。因此,不要投反对票,也不要投反对票,将帖子保留为零,并以一个有用的poi结束问题当我开始用C#编写时,有人告诉我最好使用
    using(){}
    只要有可能,但要做到这一点,您需要实现IDisposable,因此一般来说,我更喜欢通过使用来访问类,特别是在我只需要一两个类的情况下functions@Ortund您误解了。当类实现IDisposable时,最好使用
    using
    块。如果您不需要可丢弃的类,请不要使用实现它。它没有任何用途。@DanielMann使用
    块的
    的语义往往不仅仅是
    IDisposable
    接口本身的吸引力。我想,
    IDisposable
    的滥用不仅仅是为了范围的目的。如果您有任何非托管资源可以使用,这只是一个附带说明您应该包括Finalizer调用Dispose(false),这将允许GC在执行垃圾收集时调用Finalizer(如果尚未调用Dispose),并正确释放非托管资源。如果实现中没有Finalizer调用
    GC.SuppressFinalize(this);
    是指针