如果初始化失败,如何在C#中处理IDisposable对象传递给基本构造函数参数?

如果初始化失败,如何在C#中处理IDisposable对象传递给基本构造函数参数?,c#,idisposable,C#,Idisposable,如果我使用base(…)构造将IDisposable对象传递给基类构造函数,我会在FxCop中触发一个关于释放IDisposable的命令。警告在其他地方偶尔有用,所以我不想禁用它,但我意识到我不知道应该使用的确切语义 基本构造函数是否有责任用try/catch包装其主体,以确保在出现异常时正确处理IDisposable对象 相关问题: 这并不是问题的答案,但 您不一定需要完全禁用该规则-您可以在知道分析过于热情的方法中禁用该规则: [SuppressMessage("Microsoft.

如果我使用
base(…)
构造将IDisposable对象传递给基类构造函数,我会在FxCop中触发一个关于释放
IDisposable
的命令。警告在其他地方偶尔有用,所以我不想禁用它,但我意识到我不知道应该使用的确切语义

基本构造函数是否有责任用try/catch包装其主体,以确保在出现异常时正确处理
IDisposable
对象

相关问题:


    • 这并不是问题的答案,但

      您不一定需要完全禁用该规则-您可以在知道分析过于热情的方法中禁用该规则:

      [SuppressMessage("Microsoft.Reliability",
                       "CA2000:DisposeObjectsBeforeLosingScope",
                       Justification = "Your reasons go here")]
      public YourClass(IDisposable obj) : base(obj)
      {
      }
      

      尽管CA2000分析非常糟糕,完全禁用它可能更有用。

      是的,如果构造函数中出现异常,则类构造函数和
      语句调用都不会使用Dispose

      在构造函数中处理异常是您的工作,因为尚未创建的对象不能以与成功创建的对象相同的方式“释放”

      这与基本构造函数无关,而是一个更大的问题:

      class A: IDisposable
      {
          public A() // constructor
          {
              r1 = new Resource(res1_id);     // resource aquisition 
              r2 = new Resource(res2_id);     // assume exception here
          }
      
          public void Dispose()
          {
              r1.Release();           // released successfully
              r2.Release();           // what to do?
          }
      
          Resource r1, r2;
      }
      

      要遵循的简单规则是:如果你创建了它,你有责任确保它得到处理。相反地,如果一个方法(无论是构造函数还是其他方法)没有创建一次性对象,我也不会期望它处理掉它。(*创建包括调用返回IDisposable的方法。)

      所以考虑到

      public Foo(SomeDisposable obj) : base(obj) { }
      
      using (SomeDisposable obj = new SomeDisposable())
      {
          Foo foo = new Foo(obj);
      }
      
      我希望看到像这样的事情

      public Foo(SomeDisposable obj) : base(obj) { }
      
      using (SomeDisposable obj = new SomeDisposable())
      {
          Foo foo = new Foo(obj);
      }
      
      而不是

      Foo foo = new Foo(new SomeDisposable());
      
      如果你有一个用于
      Foo
      的无参数构造函数,并且你想用一个一次性对象调用基本构造函数,那么你就处于一个更加棘手的位置,这可能就是规则试图保护你的地方。我想说的是,通过对基进行编码来创建并负责IDisposable,或者在具有IDisposable参数的构造函数之间进行1:1映射来避免这种情况,这样无参数的Foo就不会调用参数化基


      但是,方法或构造函数的工作不应该是猜测您已经处理完传入的对象,因为它应该如何知道?你还可以使用它。

      我提出了一个很好的模式,作为我自己相关问题的答案,它允许安全地组合iDisposable字段的声明和初始化,并确保即使在构造函数失败时也能处理它们。代码仍然需要一点清理,但在这里似乎是恰当的


      有一件事我不知道怎么做,那就是包括事件设置/清理。拥有已分配的对象列表不会转化为需要取消绑定的事件订阅列表,即使是通过反射。

      我总是处理我创建的内容(在Helper方法/类中除外)。我不会处理我没有创建的内容(除非它来自帮助器方法/类)。从方法/类的名称中,什么是和什么不是助手应该是显而易见的。另外,如果一个类持有任何可处置的东西,我会将其设置为可处置的。事实上,听起来基类需要用一些try/catch逻辑包装它的构造函数函数体,以便在该函数体中出现异常时正确处置它被要求保管的IDisable东西。没有多少人遵循这种逻辑,但它是严格正确的。在许多情况下,接受
      IDisposable
      的构造函数也可以使用一个参数来指示新构造的对象是否应该拥有它的所有权。如果新构造的对象的使用寿命超过调用它的代码的使用寿命,那么新对象可能是唯一知道何时应调用
      Dispose
      的对象。另一方面,在其他一些情况下,提供对象的代码可能是唯一知道它应该在什么时候处理的东西。在某些情况下,两个对象可能都不知道。