C# 如何知道类是否是非托管资源的包装器

C# 如何知道类是否是非托管资源的包装器,c#,C#,如何知道C#中的类是否为非托管类,以便在自定义类中使用它时,我知道是否必须实现IDisposable接口 如果我在MSDN网络上正确地实现了这一点,那么当我使用非托管资源时,我总是必须实现IDisposable接口 因此,我创建了一个小示例,您可以在下面找到: class TestClass { private StreamReader reader; public UsingTestClass() { reader = File.OpenText("C

如何知道C#中的类是否为非托管类,以便在自定义类中使用它时,我知道是否必须实现IDisposable接口

如果我在MSDN网络上正确地实现了这一点,那么当我使用非托管资源时,我总是必须实现IDisposable接口

因此,我创建了一个小示例,您可以在下面找到:

class TestClass
{
    private StreamReader reader;

    public UsingTestClass()
    {
        reader = File.OpenText("C:\\temp\\test.txt");

        string s;
        while (!string.IsNullOrEmpty(s = reader.ReadLine()))
        {
            Console.WriteLine(s);
        }

    }
}
下面举例说明该文件是一个未更改的ressource,它也在我的测试类中使用。那么我怎么能看到,这个类是未更改的呢? 编译器和重拾器没有抱怨任何事情

提前谢谢

我如何知道C#中的类是否处于非托管状态

这会让你马上走错路,所有的C#课程都得到管理。该语言根本不支持使用非托管类。除了C++/CLI之外,没有一种.NET语言可以这样做。这是一种非常不寻常的语言,专门用来帮助程序员使用本机C++类。这种语言的使用是专门的,与这个问题无关

重要的是托管类是否是非托管资源的包装器。包装器是一种具有纯托管接口但在内部使用非托管资源的类,通常通过具有[DllImport]属性的pinvoke。资源几乎总是用
IntPtr
表示。非托管句柄或指针

这样的包装器需要一个终结器来确保非托管资源总是被释放。如果这种情况没有发生,那么你就有漏洞,这种漏洞(最终)会在操作系统对使用太多资源的程序感到不安时导致程序崩溃

由于它有一个终结器,它还实现了IDisposable。允许程序在GC开始调用终结器之前提前释放非托管资源。使用Dispose()方法或Using语句是可选的,终结器足以确保完成任务

但是,有时终结器不够好,因为程序生成垃圾的速度不够快,因此您的帮助非常重要。你不能像大多数.NET程序员那样真正知道自己是否需要帮助。在多年的编程过程中,子集从未注意到问题。我们最终确实在SO收到了他们的来信:)


您的StreamReader示例是进入下一步的好例子。StreamReader实际上并不包装非托管资源。它的所有代码都是用C#编写的,而且它没有任何pinvoke,它的身体里没有未管理的骨骼。因此没有终结器。但是仍然有一个Dispose()方法

StreamReader被“感染”。它也是一个包装类,但用于流,而不是IntPtr。纯托管抽象.NET类型,本身是包装器。它实现了IDisposable,现在StreamReader也必须实现它。因此,当调用StreamReader的Dispose()方法时,Stream.Dispose()方法可以运行

这是分层工作,有一个类的层次结构。StreamReader包装Stream,包装FileStream,包装SafeFileHandle,实际包装IntPtr。只有SafeFileHandle具有终结器


理解分层是每个人都放弃的地方,这需要对这些.NET类的结构方式有相当深入的了解。你可以到达那里,但需要几年的时间。有三种基本捷径:

  • 了解操作系统的工作原理。让您洞察到文件是操作系统资源,并确信当您使用文件时,需要处置或关闭它

  • 对于您使用的类,请使用MSDN库文章。当您看到它有一个Dispose()方法时,几乎总是有很好的理由使用它。有时没有,但无论如何,当你使用它时,你永远不会错

  • 遇到麻烦,犯下所有程序员需要犯的错误,使用SO或内存分析器来找出你做错了什么。学习如何做正确的事情从来没有错


那么,在sich情况下采取行动的最佳实践是什么?尤其是在使用第三方库的情况下?所有实现IDisposable的内容都应该在使用完毕后予以处理。代码分析应该对此有所了解,因为您有一个实现IDisposable的类成员,但是您自己既不处理它,也不实现IDisposable。
StreamReader
本身不是非托管资源,但它包装了一个,因此它实现了
IDisposable
。任何实现IDisposable的
。除此之外,您不必担心非托管资源,除非您通过PInvoke使用Windows API调用(因为任何包装以这种方式分配的资源的东西都应该实现IDisposable)。您需要仔细阅读这里的内容,伙计。文章说,
文件
访问非托管资源。它并没有说
文件
是非托管资源。这对C#开发者来说是一个很大的区别。总结:那么,如果我们在每个类中使用
using
Dispose()
,实现
IDisposable
我们总是安全的?在某些情况下,我们不想在
IDisposable
上调用
Dispose()
?我讨厌摘要,试着理解所有的单词。如果我能少用一点的话,我会的。并非“总是安全的”,不要处理在其他地方使用的对象。非常感谢您提供的详细答案。