简体   繁体   English

C ++ / CLI编译器何时创建哪种配置模式?

[英]When does the C++/CLI compiler create which dispose pattern?

This may sound like a weird question but depending on something the compiler generates different content for the dispose methods in the case of a C++/CLI class extending a C# class which implements IDisposable. 这听起来像是一个很奇怪的问题,但是在C ++ / CLI类扩展了实现IDisposable的C#类的情况下,编译器会为dispose方法生成不同的内容,具体取决于某些内容。

(If you are interested in what the dispose pattern looks like I recommend reading this or this . The latter also has information on C++/CLI. And here is an article talking explicitly about deriving a C++/CLI class from a C# class which implements IDisposable.) (如果您对处置模式的外观感兴趣,我建议您阅读本节本节 。后者也提供有关C ++ / CLI的信息。 是一篇明确讨论从实现IDisposable的C#类派生C ++ / CLI类的文章。 。)

The problem is best illustrated by showing the generated IL code (extracted with Reflector). 通过显示生成的IL代码(用Reflector提取)可以最好地说明该问题。 Version 1: 版本1:

[HandleProcessCorruptedStateExceptions]
protected override void Dispose([MarshalAs(UnmanagedType.U1)] bool A_0)
{
    if (A_0)
    {
        try
        {
            this.~Foo();
        }
        finally
        {
            base.Dispose(true);
        }
    }
    else
    {
        try
        {
            this.!Foo();
        }
        finally
        {
            base.Dispose(false);
        }
    }
}

Version 2: 版本2:

[HandleProcessCorruptedStateExceptions]
protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool A_0)
{
    if (A_0)
    {
        try
        {
            this.~Foo();
        }
        finally
        {
            base.Dispose();
        }
    }
    else
    {
        try
        {
            this.!Foo();
        }
        finally
        {
            base.Finalize();
        }
    }
}

Note that in the first version a base method Dispose(bool) is being called while in the second either Dispose() or Finalize() get called. 请注意,在第一个版本中,将调用基本方法Dispose(bool),而在第二个版本中,将调用Dispose()或Finalize()。 Both of these have been generated by almost the same code. 这两个都是由几乎相同的代码生成的。 In the second case the keyword "virtual" was omitted when defining Dispose(bool) in the base class. 在第二种情况下,在基类中定义Dispose(bool)时会省略关键字“ virtual”。

It seems like the compiler is trying to determine if the Dispose pattern is used correctly and generate appropriate code. 似乎编译器正在尝试确定是否正确使用了Dispose模式并生成适当的代码。

My problem is that I have a case where the base class looks like this: 我的问题是我遇到了一个基类如下所示的情况:

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
    if (disposing)
    {
    }
  }

but the generated code is Version 2. Now, the base Dispose() function calls Dispose(true) virtually on the derived class which in turn calls base.Dispose() and my stack overflows. 但是生成的代码是版本2。现在,基本Dispose()函数实际上在派生类上调用Dispose(true),而派生类又调用base.Dispose(),并且我的堆栈溢出。

So when does the compiler generate each version of the code? 那么,编译器何时生成代码的每个版本?

Version 1 of the code with Dispose(true) calls occurs when the base class has a non-private virtual method called Dispose(bool) . 当基类具有名为Dispose(bool)的非私有虚拟方法时,将发生具有Dispose(true)调用的代码的版本1。

Version 2 of the code with Dispose() occurs when the base class does not have a Dispose(bool) method. 当基类没有Dispose(bool)方法时,将发生带有Dispose()的代码的版本2。

There is a Version 3 of the code that looks nearly identical to Version 2 that occurs when the base class has a non-virtual Dispose(bool) method. 该代码的第3版看起来与基本类具有非虚拟Dispose(bool)方法时发生的第2版几乎相同。 The only difference is that the C++ Dispose(bool) function also has the new keyword on it. 唯一的区别是C ++ Dispose(bool)函数还具有new关键字。

I can get your situation to happen by doing the following: 通过执行以下操作,我可以使您的情况发生:

  1. Make a C# class that implements IDisposable without a Dispose(bool) method. 使一个IDisposable类实现IDisposable而不使用Dispose(bool)方法。
  2. Do a full compile of the C# and C++ libraries. 对C#和C ++库进行完整编译。
  3. Modify the C# class to add a virtual Dispose(bool) method. 修改C#类以添加虚拟Dispose(bool)方法。
  4. Compile (but do NOT rebuild all). 编译(但不要全部重建)。

In this case the C# code is generated correctly but the C++ code does not adjust the Dispose(bool) function to be what it should 在这种情况下,C#代码会正确生成,但是C ++代码不会将Dispose(bool)函数调整为应有的值

The fix for this is very simple: A rebuild-all turns the broken Version 2 code into the proper Version 1 code. 修复非常简单:全部重建将损坏的版本2代码转换为正确的版本1代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM