在 C# 中实现 IDisposable [重复]

Posted

技术标签:

【中文标题】在 C# 中实现 IDisposable [重复]【英文标题】:Implementing IDisposable in C# [duplicate] 【发布时间】:2017-01-21 23:46:36 【问题描述】:

我正在尝试在示例程序中实现 IDisposable。如果我在 using 块语句中使用 SqlConnection 类,它会自动处理它。

public int testCon()

    using (SqlConnection conn = new SqlConnection("Conn string"))
    
        using (SqlCommand cmd = conn.CreateCommand())
        
            conn.Open();
            cmd.CommandText = "SELECT COUNT(1) FROM Carsd";

            return (int)cmd.ExecuteScalar();
        
    

我创建了一个类并实现了 IDisposable。我在 using 块语句中创建了一个新实例。

class Program 

    static void Main(string[] args)
    
        testDispose objTestDispose;

        using (objTestDispose = new testDispose())
        
            objTestDispose.UserName = "testUser";
            objTestDispose.PassWord = "testPassword";                                
        

        Console.WriteLine("Check obj of testDispose Class" + objTestDispose.UserName);
        Console.WriteLine("Check obj of testDispose Class" + objTestDispose.PassWord);
        Console.ReadLine();

            


public class testDispose : IDisposable

    public string UserName  get; set; 
    public string PassWord  get; set; 

    public void Dispose()
                   

我相信,使用 block 会自动调用 dispose 方法。因此,如果我在 using 块中创建一个新实例,它将在现有 using 块之后被处置。但是,我仍然可以在 using 块之外访问 objTestDispose 对象。为什么?

请提出建议。

UDPATE

BWA 先生..感谢您重复我的问题。但你应该知道我是一名学生并且正在学习。我心中有这个问题,所以我在这里问了。 **您不能说 IDisposable 接口仅适用于非托管资源。**我也可以删除托管资源。这取决于实际情况。根据以下link -

如果您的对象已分配 250MB System.Drawing.Bitmap(即 .NET 托管的 Bitmap 类)作为某种帧缓冲区,该怎么办?当然,这是一个托管的 .NET 对象,垃圾收集器会释放它。但是你真的想留下 250MB 的内存就坐在那里——等待垃圾收集器最终出现并释放它吗?如果有一个开放的数据库连接怎么办?当然,我们不希望该连接处于打开状态,等待 GC 完成对象。

如果用户调用了 Dispose()(意味着他们不再打算使用 对象)为什么不摆脱那些浪费的位图和数据库 连接?

所以现在我们将:

摆脱非托管资源(因为我们必须这样做),并摆脱 托管资源(因为我们希望提供帮助)

【问题讨论】:

因为你在 using 块之外声明了它。它不会神奇地消失。 即使您在using (SqlConnection conn = new SqlConnection("Conn string")) 之外声明某些内容,它也会在之后存在,因为许多其他人也在发布。 你读过this、this或this吗? 已丢弃!= 垃圾收集 不要混淆更新中的问题 - 没有人说 IDisposable 用于非托管资源而不是托管。当然,如果您愿意,它可以同时用于两者。正如我所说,合同约定 Dispose() 将被调用,因此这是处置非托管资源的最有效方式。如果你想在Dispose() 中做其他事情,那就这样吧。 【参考方案1】:

Dispose 正在被调用,但它不会做任何事情来破坏对象本身(您会注意到框架中的许多 IDiposable 类还有一个 IsDisposed 属性来指示非托管资源是否释放)

【讨论】:

【参考方案2】:

您仍然可以访问它,因为您在 using 块的范围之外定义了它,并且您没有将它设置为 null。

请注意,using 没有将对象设置为 null,它只是意味着您的 Dispose() 方法将被调用,这为您提供了一种合同保证的方式来处理任何否则不会被清理的非托管资源由垃圾收集器。

你还应该考虑你的陈述的逻辑:

我相信,使用 block 会自动调用 dispose 方法。所以,如果我在 using 块中创建一个新实例,它将在存在 using 块之后被处置。

... 一个对象如何将它自己的 self 设置为 null?

【讨论】:

先生。您能否告诉我如何在代码中测试Dispose 对象。这对我有帮助。 Dispose() 实际上对于处理托管资源更有用。 @Mohit objTestDispose 将在某个阶段自动(在大多数情况下)在超出范围后被垃圾收集器清除(在您的情况下,它会在 Main () 结束了,但这也巧合的是应用程序的结束)。去仔细阅读链接问题中的信息,它涵盖了IDisposable 的实现。【参考方案3】:

来自MSDN

IDisposable 接口

提供释放非托管资源的机制。

这个接口的主要用途是释放非托管资源。 垃圾收集器自动释放分配给 不再使用该对象时的托管对象。然而,它不是 可以预测何时会发生垃圾收集。此外, 垃圾收集器不了解非托管资源,例如 窗口句柄,或打开的文件和流。使用 Dispose 方法 这个接口显式释放非托管资源 与垃圾收集器结合使用。对象的消费者可以 当不再需要对象时调用此方法。

这用于释放未命名的资源,而不是用于销毁对象本身。

【讨论】:

以上是关于在 C# 中实现 IDisposable [重复]的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中实现接口与显式实现接口 [重复]

如何在 C# 中实现 const 正确性? [复制]

您将如何在 C# 中实现“特征”设计模式?

c# 泛型类型和存储库模式

C# 中实现对List中的数据查重操作

C#中IDisposable的用法