IDisisable - 在没有外部引用的情况下在课堂上处理什么?

时间:2016-12-27 09:44:44

标签: c# dispose

我有小助手班。这些类在内部用于确保某些类型的字符串始终具有适当的格式(邮件地址,电话号码,ID,URL,键,颜色......)。

我想将它们放入使用块中,以便能够回收变量名称:

using(Id id = ids.First())
{
    Container container = containers.getById(id);
    ...
}
foreach(Id id in ids.Skip(1))
{
    Container container = containers.getById(id);
    ...
}

当我这样做时,Visual Studio要求我将这些类标记为Disposable,我做了,但我不知道如何处理方法存根。我们以“邮件地址”类为例:

public class MailAddress : IEquatable<MailAddress>, IDisposable
{
    const string MAILADDRESSPATTERN = ...
    protected string _address;
    public MailAddress(string address)
    {
        if (address == null) throw new ArgumentNullException("address");
        if (!Regex.IsMatch(address, MAILADDRESSPATTERN)) throw new ArgumentException("address");
        this._address = address.ToLower();
    }

    bool IEquatable<MailAddress>.Equals(MailAddress other)
    ...
    public override int GetHashCode()
    ...
    ...
    ...
    public override string ToString()
    ...

    public void Dispose()
    {
        throw new NotImplementedException();
    }
}

Dispose函数究竟要在这样的类中做什么?我需要处理什么,以及垃圾收集器会自动执行什么操作?

到目前为止,我没有在任何地方打电话给Dispose,它似乎工作正常。现在,该课程为Disposable,我是否必须在整个代码中添加对Dispose的调用?

4 个答案:

答案 0 :(得分:6)

不要这样做,你滥用语言和Disposable接口/模式。

IDisposable有非常具体的原因,其中包括非托管资源的确定性释放,或者当您的班级拥有一次性参考资料时。

绝对不是创建本地范围的方法,因此您可以重用变量名称。如果您需要这样做,只需:

{
    Id id = ids.First())
    Container container = containers.getById(id);
    ...
}

答案 1 :(得分:5)

编译器强制您在IDiposable类中实现Id接口,因为您将其与using一起使用。 using的唯一目的是在您离开后调用IDisposable.Dispose。因此,您只能在IDisposable实施中使用它。

IDisposable的目的是在不再使用对象时清理外部资源。这包括关闭文件,断开与数据库的连接,返回窗口句柄等等。

由于您似乎无法进行清理,因此您无需使用using语句。在那些 使用using的情况下(例如,您对一些具有外部资源的不同类型的对象使用一种方法),您仍然必须实现{{1}方法来满足接口,但你可以把它留空。

如果你的课程是一次性的,你确实应该在你不再需要的时候处理它,即使Dispose什么都不做。如果您或其他人稍后向Dispose添加清理代码,您应该依赖它执行。

答案 2 :(得分:3)

您的Dispose方法完全没有用处,因为您似乎没有任何非托管资源。 Dispose仅在您要手动处理这些资源时才有用。

GC会对所有受管资源进行垃圾收集,因此您无需采取任何操作。删除课程中的IDisposable似乎是合适的操作。这也需要删除无用的using,你可以换成简单的括号:

{
    Id id = ids.First();
    Container container = containers.getById(id);
    ...
}

答案 3 :(得分:1)

不确定您使用using关键字的原因。当执行离开using的范围时,Dispose()关键字会保留对using的调用。因此,using括号内的对象必须是IDisposable。如果您没有任何需要清理的资源,则无需将对象包装在using中。由于在.net中使用析构函数不是一个好主意,因此您在析构函数中放置的逻辑通常放在Dispose()方法中。这允许在与using关键字结合使用时进行受控资源管理。