Dispose List的扩展方法不起作用

Rob*_*cks 1 c# oop extension-methods dispose idisposable

我写了一个简单的扩展方法来处理列表中的所有项目:

public static void Dispose(this List<IDisposable> list) {
    for (int i = 0, il = list.Count; i < il; i++) {
        list[i].Dispose();
    }
    list.Clear();
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试使用它时,VS IntelliSense不会在下拉列表中列出它,并且在编译时找不到该方法.我如何使其工作?

List<Bitmap> bitmaps = new List<Bitmap>();
bitmaps.Dispose(); // Error: List<Bitmap> does not contain a definition for Dispose()
Run Code Online (Sandbox Code Playgroud)

afr*_*hke 7

试试这个:

public static void Dispose<T>(this List<T> list) where T : IDisposable {
    for (int i = 0, il = list.Count; i < il; i++) {
        list[i].Dispose();
    }
    list.Clear();
}
Run Code Online (Sandbox Code Playgroud)

快速解释:A List<Bitmap>是位图列表,而不是IDisposables列表,即使位图本身是IDisposable.然而,位图列表是T或更精确的列表:T的列表,其中T实现IDisposable.所以编译器很乐意接受上面的扩展方法.

进一步(因为这是一个很好的例子):

List<T>据说它的类型参数是不变的.因此,不允许以下赋值,并将产生编译器错误:

List<IDisposable> l = new List<Bitmap>();
Run Code Online (Sandbox Code Playgroud)

并且以下类型转换都不是:

List<Bitmap> lb = new List<Bitmap>();
List<IDisposable> ld = (List<IDisposable>)lb;
Run Code Online (Sandbox Code Playgroud)

但是,如果您使用的是.NET 4(其中引入了类型参数的方差)并且您使用具有协变类型参数(例如IEnumerable<out T>)的泛型类型,则以下类型转换将变为有效:

List<Bitmap> lb = new List<Bitmap>();
IEnumerable<IDisposable> ld = lb;
Run Code Online (Sandbox Code Playgroud)

并且确实为你隐晦地完成了.在这种情况下,以下扩展方法也适用:

// In a static class:
public static void Dispose(this IEnumerable<IDisposable> e) {
    foreach(var x in e) {
        x.Dispose();
    }
}

// Somewhere else:
List<Bitmap> l = new List<Bitmap>();
l.Dispose();
Run Code Online (Sandbox Code Playgroud)