识别Visual Studio中的可处置对象?

tez616oj  于 2022-12-14  发布在  其他
关注(0)|答案(9)|浏览(145)

建议在using语句中或通过调用Dispose()方法释放IDisposable对象。我发现在Visual Studio中确定对象是否可释放并不直观。
我的问题是:有没有办法在VS中识别IDisposable对象?

mgdq6dx1

mgdq6dx11#

如果你想在VS中以不同的方式突出一次性对象,请查看这个post。我个人更喜欢Resharper answer,因为我总是使用R#。
如果你只是想弄清楚你的对象是否是某个接口的示例,你可以右键单击变量名和Navigate -> Object BrowserGo to Declaration,然后右键单击类名Go to Definition/Peek Definition

您可能会喜欢Peek Definition,因为它内联显示了您需要的所有内容:

你总是可以检查对象有什么方法,如果它有Dispose()方法,那么99.9%它是一个一次性对象。我给予这个0.01%给那些给方法起坏名字的人:)。

qc6wkl3g

qc6wkl3g2#

如果你的edition of Visual Studio支持它,我建议你打开Code Analysis来构建。
完成后,选择你喜欢的任何规则集,只要它们至少能确保覆盖CA2000(在失去作用域之前处置对象)、CA2213(应处置可处置字段)和CA2202(不要多次处置对象)规则。这样,如果你没有正确处理可处置对象,编译器应该会对你“大喊大叫”。
(尽管请注意,让编译器 * 不 * 标记可处置对象的某些使用可能会变成更大的挑战,正如许多StackOverflow问题可以证明的那样)

omhiaaxx

omhiaaxx3#

您可以使用对象浏览器查看具有实现的接口的类继承层次结构

w8ntj3qf

w8ntj3qf4#

为了完整起见,如果您不想知道如何在代码中检查它,而只是想知道如果该类型实现了IDisposable这样的接口,可以在哪里查找,那么您可以始终查看MSDN
例如FileStream

  • 在备注部分已经提到:

此类型实现IDisposable接口。使用完此类型后,应直接或间接释放它。若要直接释放此类型,请在try/catch块中调用其Dispose方法。若要间接释放它,请使用语言构造,如使用(在C#中为)或使用(在Visual Basic中为)。如需详细信息,请参阅IDisposable界面主题中的〈使用实作IDisposable的对象〉一节。

  • 或者搜索Dispose method。在那里你可以看到这个类或者任何父类是否实现了IDispable。在这种情况下,它是从Stream继承的,Stream实现了在类语法和备注部分提到的接口。
public abstract class Stream : MarshalByRefObject, IDisposable

如果您想知道如何在Visual Studio中查找接口的实现,这里已经有一个问题可以回答:
How do you find all implementations of an interface?

5gfr0r5j

5gfr0r5j5#

要查看一个类实现了什么接口,沿着它所有公开的字段、属性、方法等,一种方法是在代码中找到该类。例如:

Image image = Image.FromFile(path);

确保单击类而不是示例,然后按F12。这将转到该类的元数据文件。例如:Image.cs文件具有以下上述类声明:

public abstract class Image : MarshalByRefObject, ISerializable, ICloneable, IDisposable

然后,您也可以使用F12来单击其他类。请注意,这些类在Visual Studio中通常以浅蓝色显示:

您还可以通过右键单击类并从下拉列表中选择“Go To Definition”来访问此 meta数据文件。
虽然不太理想,但您也可以转到类的示例,并在末尾放置一个.。这应该会打开intellisense,如果项实现了接口,您将能够在列表中看到Dispsose()
你也可以只写myInstance.Dispose();using (myInstance = new MyClass()) {},如果它编译,类实现接口,否则它不。

dhxwm5r4

dhxwm5r46#

作为对Resarper及其同类产品的一个(愚蠢的?)替代方案,Visual Studio确实有 * 外部工具 * 的概念(在“工具”菜单中),您可以(ab)使用它来做如下事情:

*标题:Is Disposa&ble
*命令:C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
*参数:-Command "&{$i=[Type]::GetType('System.IDisposable');[AppDomain]::CurrentDomain.GetAssemblies()|%{ $_.GetTypes()}|?{$_.FullName.EndsWith('.$(CurText)')}|%{New-Object PSObject -Property @{'Type'=$_;'IDisposable'=$i.IsAssignableFrom($_)}}|ft}"
***使用“输出”窗口:***选中 *

这将读取您在编辑器中选择的任何字符串,搜索以该字符串为名称的.NET类型,并显示该字符串是否实现IDisposable的True/False。
该工具中的Powershell命令是我所能做的演示这种可能性的 * 最快 * 的方法,但它远非完美--它只查找Powershell默认加载的程序集中的类型。如果您想扩展这个想法,可以构建一个命令行.NET应用程序,该应用程序加载您的项目并扫描您的项目加载的所有程序集。
例如,如果在代码中突出显示单词Stream,并运行外部工具(在示例中为ALT+T、ALT+B),则将返回:

Type             IDisposable
----             -----------
System.IO.Stream        True

要分解Powershell命令,请执行以下操作:

&{ $i=[Type]::GetType('System.IDisposable');        # Get the IDisposable interface
   [AppDomain]::CurrentDomain.GetAssemblies() `     # Get all loaded assemblies
    | %{ $_.GetTypes() } `                          # For each assembly, get all types
    | ?{ $_.FullName.EndsWith('.$(CurText)') } `    # Filter types that are named $(CurText) - $(CurText) is a macro within VS External Tools
    | %{ New-Object PSObject -Property @{           # For each type, return an object containing...
         'Type' = $_;                               # ...the type name...
         'IDisposable' = $i.IsAssignableFrom($_)    # ...and whether the IDisposable interface is implemented
       } } `
    | ft }                                          # Format all returned objects as a table
y0u0uwnf

y0u0uwnf7#

找出这一点最简单方法是使用代码分析中内存警告
1.对项目属性启用代码分析以“生成时运行”。

1.生成后查看以下警告


建立IDisposable型别的区域对象,但在对象的所有指涉都超出范围之前,不会处置对象。


实作System.IDisposable的型别会宣告属于也实作IDisposable之型别的字段。宣告型别的Dispose方法不会呼叫字段的Dispose方法。

wtzytmuj

wtzytmuj8#

either using or in Dispose() method在可能的情况下使用using构造。原因如下。使用此MSDN示例,以下是两个等效的代码块。此代码块使用using

using (Font font1 = new Font("Arial", 10.0f)) 
{
    byte charset = font1.GdiCharSet;
}

这一个没有using

{
    Font font1 = new Font("Arial", 10.0f);
    try
    {
        byte charset = font1.GdiCharSet;
    }
    finally
    {
        if (font1 != null)
            ((IDisposable)font1).Dispose();
    }
}

第二块的每一部分都是有原因的:花括号、try-finally、null检查和向IDisposable的转换。不应期望任何人记住这些。这就是using构造存在的原因。

ktca8awb

ktca8awb9#

可以在C#7中完成的干净的事情

class Foo : IDisposable {
    string _bar = "init";
    void Fooy() { _bar = "fooy"; }

    public void Dispose() {
        _bar = null;       
    }

    static void Main()
    {
        var v = new Foo();
        Console.WriteLine(v._bar);
        if(v is IDisposable id) using(id)
            v.Fooy();
        else
            v.Fooy();

        Console.WriteLine(v._bar ?? "null");;

    }
}

Fooy可能是某个 virtualabstract 函数。某些基类可能实现IDisposable,而其他基类则没有。请尝试运行上面的代码。控制台将根据IDisposable是否已实现而打印不同的文本

相关问题