在C#中处理对象的正确方法?

时间:2015-02-18 20:21:35

标签: c# dispose

嗨,我是这个伟大社区的新人,我有第一个问题。希望这个人在正确的地方(我希望我的英语是正确的):

我是新手开发者,我必须改进C#应用程序,所以我找到了这个代码,我想知道这是否是正确的方法

ObjClass obj = new ObjClass();
obj.SomeText = TextBox1.Text;
obj.SomeNumber = Convert.ToInt32(TextBox2.Text);

ObjClass的定义如下:

    using System;

namespace SomeObject
{
    public class ObjClass : IDisposable
    {
        public string SomeText { get; set; }
        public int SomeNumber{ get; set; }

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

然后在使用对象后,完成或处理objecto的代码如下:

if(obj.SomeNumber != null)
{
    //doing something else
    obj.Dispose();
}

3 个答案:

答案 0 :(得分:2)

正确的方法是不要编写Dispose函数。最好的情况是你只是绑定GC,阻止它释放你的对象,直到它在GUI线程上调用它(减慢它)并得到它已经运行的确认。在最坏的情况下,你写得和你一样糟糕,并最终导致潜在的内存泄漏。

现在,如果您直接在对象中处理本机内存或资源(并且它很少见,您可以避免处理大部分内容或将其留给.NET),这是编写终结器的正确方法(即部分你错过了!)是:

public class Base: IDisposable
{
    private bool disposed = false;

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

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Free other state (managed objects).
            }
            // Free your own state (unmanaged objects).
            // Set large fields to null.
            disposed = true;
        }
    }

    // Use C# destructor syntax for finalization code.
    ~Base()
    {
        // Simply call Dispose(false).
        Dispose (false);
    }
}

如果您的代码只是阻止终结器运行,则此代码会在终结器中调用Dispose(false)(即,当GC确定您的对象无用并尝试释放它时)或Dispose(true) Dispose()你自己(然后阻止GC调用终结器,这样你就不会两次处理)。

至于你如何使用它,这是正确的方法:

using(var obj = new Base())
{
   // do whatever you want
   // obj.Dispose() will automatically be called at the end of scope
}

在功能上等同于:

try
{ 
   var obj = new Base();  
   // use the object
} 
finally 
{
   // always called, even during exception stack unwinding  
   obj.Dispose();
}

同样,正确的方法不是写Dispose。每当您被要求这样做时,框架的失败就是为您提供适当的工具来留在管理的世界中。现在这些实例越来越少。

答案 1 :(得分:1)

如果一个类是一次性的,确保它被处置的最好方法是使用using块。

using(var foo = new ObjClass())
{
    // do something
}

这将确保即使发生异常也会处置对象。

答案 2 :(得分:0)

欢迎来到IDisposable的精彩世界!我认为这是两个问题:

1)ObjClass的实现是否正确 - 是否需要实现IDisposable
一个类应该实现IDisposable:
一个。因为它包含非托管资源。如果适用,请使用"标准IDispose实现" (搜索,你会发现)。 这种情况实际上非常罕见。这个类似乎不是这样的 - 它只管理了两个成员。
湾因为该类包含实现IDisposable的托管对象,并且您希望类的用户能够控制何时释放那些管理对象所拥有的资源。请注意,它不是关于如何释放资源 - 它们最终将被GC释放 - 但是通过提供IDisposable,您可以让类用户控制何时发生这种情况。这里一个很好的例子是一个包含托管Socket对象的类。 Socket实现了IDisposable,它将关闭端口。通过类实现IDisposable并在其Dispose方法中处理套接字,您允许类用户控制套接字何时关闭。
以上都不是。或b。这里的类是这样的,因此在这里实现IDisposable似乎是错误的。

2)ObjClass实例的使用方式是否正确?
当你完成一个对象时,可以明确地调用Dispose - 这样做没有严格的错误。但是,using语句是首选的方法。重要的是(如在另一个答案中所提到的),使用块包括幕后的try / catch和最终处理对象 - 这是重要的。如果你不使用"使用"如果有异常,你应该尝试使用catch来处理对象。