Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使IDisposable对象成为类变量?_C#_Active Directory_Idisposable_Class Variables - Fatal编程技术网

C# 如何使IDisposable对象成为类变量?

C# 如何使IDisposable对象成为类变量?,c#,active-directory,idisposable,class-variables,C#,Active Directory,Idisposable,Class Variables,我正在使用C#处理Active Directory。实例化PrincipalContext对象似乎很昂贵,因此我想将其存储在类变量中 当使用PrincipalContext作为局部变量时,我可以使用方便的使用语法。在静态变量中存储IDisposable对象时,如何确保正确处理该对象?通常的模式是在类上实现IDisposable接口。举个例子: public class YourClass : IDisposable { private OtherDisposableType yourRe

我正在使用C#处理Active Directory。实例化
PrincipalContext
对象似乎很昂贵,因此我想将其存储在类变量中


当使用
PrincipalContext
作为局部变量时,我可以使用方便的
使用
语法。在静态变量中存储
IDisposable
对象时,如何确保正确处理该对象?

通常的模式是在类上实现
IDisposable
接口。举个例子:

public class YourClass : IDisposable
{
    private OtherDisposableType yourResource;

    public YourClass()
    {
        yourResource = new OtherDisposableType();
    }

    public void Dispose()
    {
        yourResource.Dispose();
    }
}
这至少是你需要做的

编辑

我以前的版本主张在所有情况下都遵循终结器模式,这被(正确地)指出是违反框架设计准则的。但是,在实际处理非托管资源的情况下(例如,进行直接的P/Invoke调用并获取需要显式释放的句柄)建议您创建一个终结器,并在其中调用
Dispose
,以防有人使用您的代码而不调用
Dispose

public class YourClass : IDisposable
{
    private OtherDisposableType yourResource;

    public YourClass()
    {
        yourResource = new OtherDisposableType();
    }

    public void Dispose()
    {
        yourResource.Dispose();

        GC.SuppressFinalize(this);
    }

    ~YourClass()
    {
        Dispose();
    }
}

因此,基本上您希望缓存一个昂贵的资源。这是件好事

全局数据(在这种情况下是静态变量)不是一件好事,IMHO。相反,为什么不将其作为实例变量并控制其生存期呢

编写处理广告职责的类,让它创建和使用PrincipalContext,并使其也可IDisposable(使用)。从中提取一个接口以使其解耦,并使使用它的类更易于测试


想要使用AD服务的类将采用新接口(或DI)的构造函数参数。您可以在using块中手动创建类并将其传递给类,也可以使用。您可以让框架将AD对象的生存期设置为容器的生存期(也可以是IDisposable)。有关这方面的更多信息,请参阅和您的DI容器文档。

查看
System.ComponentModel
命名空间的作用。基本上,我通常使用的模式是拥有一个子组件集合,其中包括我拥有的所有不是“值”的东西——无论它是否实现了
IDisposable

然后,当我自己
Dispose()
时,我迭代这个集合并
Dispose
实现
IDisposable
的任何东西

这种技术的一个优点是,如果我拥有的对象一开始不是一次性的,但后来添加了
IDisposable
接口,那么我的类将在不必更改的情况下做正确的事情


此外,使用DI/IoC容器可以为您解决大部分问题。

您希望何时处置它?好问题我在想当类型是垃圾收集的时候。当GC检测到内存中的对象没有留下对该类型实例的引用时,可能会发生这种情况?@Ben:不要依赖GC来处理对象。任何实现IDisposable的对象都必须被决定性地处理掉,否则它将无法实现接口。GC收集是动态的,永远不会保证发生。有些CLR类型永远不会被GC收集。如果您不
Dispose
它们,它们将一直存在于您的应用程序中,直到关闭为止,无论对象是否引用它们。@kyoryu-出于兴趣,您能给我一个这样的CLR类型的示例吗?非常感谢,但是当实例符合GC条件时,不会调用析构函数吗,我希望我的静态变量在实例间保持不变?@Ben:我不推荐使用静态变量。如果您强烈认为需要这样做,那么唯一的方法就是在类上添加一个静态
Dispose
方法,在应用程序关闭时(或在任何适当的时间)显式调用该方法。它一开始就很好。但在建议实现终结器后,情况变得越来越糟。删除它,你会得到一个很好的答案。实际上,Microsoft建议不要创建终结器,除非你处理的是非托管资源。即使这样,您通常也可以通过使用像SafeHandle这样的包装来避免它。有关详细信息,请参阅《框架设计指南》一书中有关Dispose模式的部分。您不应该从终结器中调用其他对象-它们自己可能已经被终结了!如果对象正在包装一些必须完全释放的非托管资源,那么它已经有了自己的终结器。我非常喜欢这个答案,谢谢。产生的讨论在我脑海中留下了一个学术问题,即如何最好地处理存储在类变量中的IDisposable类型的处理(这可能是由于我的理解不足)。@Ben-谢谢!我同意我们还没有回答这个问题(尽管Adam Robinson关于静态Dispose方法的评论值得考虑)。我倾向于将静态/类变量(除了字符串和正则表达式之类的只读不可变变量)视为代码气味,类似于其他语言中的全局变量。关于这一点的有趣讨论:不完全是我所说的——不一定是一次性集合,而是存储在集合中的对象的任何子组件(不管是哪种类型的)。一次性收集的想法听起来有点吓人,尽管我现在还不太清楚为什么。