IDisposable - 在没有外部引用的情况下在 class 中处理什么?

IDisposable - what to Dispose in class without external references?

我有小帮手class。 classes 在内部用于确保某些类型的字符串始终具有适当的格式(邮件地址、phone 数字、id、url、键、颜色...)。

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

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

当我这样做时,Visual Studio 要求我将这些 class 标记为 Disposable,我照做了,但我不确定如何处理方法存根。我们以"Mail Address"class为例:

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 函数在这样的 class 中究竟需要做什么?我必须处理什么,垃圾收集器会自动做什么?

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

编译器强制您在 Id class 中实现 IDiposable 接口,因为您将它与 using 一起使用。 using 的唯一目的是在你离开它的块后调用 IDisposable.Dispose。所以你只能在 IDisposable 实现上使用它。

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

因为您似乎没有要清理的东西,所以您不需要 using 声明。在那些你 来使用 using 的情况下(例如,你对不同类型的对象使用一种方法,其中一些对象有外部资源),你仍然必须实现 Dispose方法来满足接口,但可以留空。

如果您的 class 是一次性的,那么您确实应该在不再需要它时丢弃它,即使 Dispose 什么也不做。如果您或其他人稍后将清理代码添加到 Dispose,您应该依赖它被执行。

您的 Dispose 方法根本没有用处,因为您似乎没有任何非托管资源。 Dispose 仅在您想手动处理这些资源的情况下有用。

所有托管资源都由 GC 进行垃圾回收,因此您无需执行任何操作。删除 class 上的 IDisposable 似乎是合适的操作。那也需要删除无用的 using ,您可以将其换成简单的括号:

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

不要这样做,你在滥用语言和 Disposable 界面/模式。

IDisposable 存在的原因非常具体,其中包括非托管资源的确定性释放,或者当您的 class 拥有一次性引用时。

这肯定不是创建局部作用域的方法,因此您可以重用变量名。如果您需要这样做,只需执行:

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

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