相关疑难解决方法(0)

"Dispose"只应用于包含非托管资源的类型吗?

我最近与同事讨论了Dispose实施的价值和类型IDisposable.

我认为即使没有非托管资源可以清理IDisposable,应该尽快清理类型.

我的同事有不同的想法; 执行IDisposable,如果你没有任何非托管资源为你的类型,最终会被垃圾收集是没有必要的.

我的论点是,如果你有一个想要尽快关闭的ADO.NET连接,那么实现IDisposable并且using new MyThingWithAConnection()有意义.我的同事回答说,在封面下,ADO.NET连接是一种非托管资源.我对他回复的答复是,最终所有东西都是一种非托管资源.

我知道推荐的一次性模式,如果Dispose被调用,你可以免费使用托管和非托管资源,但是如果通过终结器/析构函数调用,则只有免费的非托管资源(前面有关于如何提醒消费者不正确使用您的IDisposable类型的博客)

所以,我的问题是,如果你有一个不包含非托管资源的类型,是否值得实现IDisposable

c# garbage-collection idisposable finalization finalizer

65
推荐指数
7
解决办法
4185
查看次数

垃圾收集器调用Dispose()吗?

我认为如果您的程序没有,GC会最终调用Dispose,但是您应该在程序中调用Dispose()以使清除确定性.

但是,从我的小测试程序来看,我根本没有看到Dispose被调用....

public class Test : IDisposable
{
    static void Main(string[] args)
    {
        Test s = new Test();
        s = null;
        GC.Collect();
        Console.ReadLine();
    }

    public Test()
    {
        Console.WriteLine("Constructor");
    }

    public void Dispose()
    {
        Console.WriteLine("Dispose");
    }
}
Run Code Online (Sandbox Code Playgroud)

//输出只是"构造函数",我没有像我期望的那样得到"Dispose".这是怎么回事?

编辑:是的,我知道我应该调用Dispose() - 我在使用一次性物体时遵循标准模式.我的问题出现了,因为我试图追踪某些elses代码的漏洞,这是托管C++(另一层复杂性,这将是另一个线程的好主题).

.net c# memory garbage-collection dispose

60
推荐指数
1
解决办法
4万
查看次数

我是否需要在托管对象上调用Dispose()?

我无法相信我仍然对此感到困惑但是,无论如何,让我们最终指出:

我有一个类覆盖OnPaint来做一些绘图.为了加快速度,我在构造函数中预先创建了笔,画笔等,以便OnPaint不需要继续创建和处理它们.

现在,我确保我总是处理这些对象,但我感觉我不需要,因为尽管它们实现了IDisposable,但它们都是托管对象.

它是否正确?


感谢所有的答案,这个问题肯定已被钉上了.
我很高兴我一直保持警惕,总是使用'​​使用',所以我不需要经历所有的代码检查.我只想清楚我不是一个毫无意义的用户.

顺便说一句,我确实有一个奇怪的情况,最近,我不得不更换一个使用块并手动调用dispose!我会把它挖出来并创造一个新问题.

.net idisposable

28
推荐指数
3
解决办法
6312
查看次数

将MemoryStream包装在一个使用中

我已经告诉System.IO.MemoryStream不必在被包装使用的块,因为没有基本的资源,这有点违背我一直都告诉流("如有疑问,请使用使用 ") .

这是真的?为什么MSDN示例使用一个(总结如下)?

using(MemoryStream memStream = new MemoryStream(100))
{
            // do stuff
}
Run Code Online (Sandbox Code Playgroud)

.net c# stream

10
推荐指数
4
解决办法
6137
查看次数

依赖于.NET自动垃圾收集器是不好的做法吗?

可以创建大量内存密集型对象,然后放弃对它们的引用.例如,我可能想要从数据库下载和操作一些数据,我将进行100次单独的下载和处理迭代.我可以声明一次DataTable变量,并且对于每个查询,使用构造函数将其重置为新的DataTable对象,从而放弃内存中的旧DataTable对象.

DataTable类具有简单的内置方式来释放它使用的内存,包括Rows.Clear()和.Dispose().因此,在将变量设置为新的DataTable对象之前,我可以在每次迭代结束时执行此操作.或者我可以忘掉它,让CLR垃圾收集器为我做这件事.垃圾收集器似乎非常有效,因此最终结果应该是相同的.当你不需要它们时,显然处理内存繁重的对象(但是添加代码来执行此操作)或者只是依靠垃圾收集器为你做所有的工作(你受到了摆布GC算法,但你的代码更小)?

根据要求,这里是代码说明了回收的DataTable变量示例:

    // queryList is list of 100 SELECT queries generated somewhere else.
    // Each of them returns a million rows with 10 columns.
    List<string> queryList = GetQueries(@"\\someserver\bunch-o-queries.txt");
    DataTable workingTable;

    using (OdbcConnection con = new OdbcConnection("a connection string")) {
        using (OdbcDataAdapter adpt = new OdbcDataAdapter("", con)) {
            foreach (string sql in queryList) {
                workingTable = new DataTable();  // A new table is created. Previous one is abandoned
                adpt.SelectCommand.CommandText = sql;
                adpt.Fill(workingTable);
                CalcRankingInfo(workingTable);
                PushResultsToAnotherDatabase(workingTable);
                // Here I could call workingTable.Dispose() …
Run Code Online (Sandbox Code Playgroud)

.net garbage-collection

5
推荐指数
2
解决办法
4817
查看次数

与C#析构函数相关的成本(又名:终结者)?

析构函数应该只释放对象所持有的非托管资源,并且不应该引用其他对象.如果您只有托管引用,则不需要(也不应该)实现析构函数.您希望这仅用于处理非托管资源.因为拥有析构函数需要一些成本,所以你应该只在消耗有价值的非托管资源的方法上实现它.

- C#程序员的C#十大陷阱

文章没有深入讨论这个问题,但在C#中使用析构函数会涉及哪些成本?

注意:我知道GC以及在可靠的时候没有调用析构函数的事实,除此之外,还有什么吗?

c# destructor idisposable finalizer

3
推荐指数
2
解决办法
1179
查看次数

我应该在IDisposable和Finalize上实现GC.SupressFinalize吗?

我新客户所在的代码审查清单如下 -

实现Dispose和Finalize的类应该在Dispose实现中调用GC.SupressFinalize

为什么?

它是否应该读取为实现IDisposable接口的类应该在Dispose实现中调用GC.SupressFinalize?

或者我错过了一些愚蠢的东西?

.net garbage-collection idisposable finalizer suppressfinalize

2
推荐指数
1
解决办法
462
查看次数

我是否需要使用Font,Brush等模式

使用GDI +进行编程时,我是否需要坚持使用模式来处理各种对象,如Brush,Font,这会使代码变得非常混乱.

有什么建议?

.net c# gdi+ gdi

1
推荐指数
1
解决办法
731
查看次数