65.9K
CodeProject 正在变化。 阅读更多。
Home

万能的 .NET 语言 - C++/CLI

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (3投票s)

2009 年 7 月 1 日

CPOL

3分钟阅读

viewsIcon

23608

downloadIcon

94

作者展示了实现 C# 中已知的 using 语句是多么容易。

引言

在 C# 中安全释放资源有两种方法,分别是 try-finallyusing 语句。 Try-finally 允许调用 IDisposable 接口引入的 Dispose 方法,而 using 语句会自动调用它。 这两种方法都能确保在出现异常时不会发生资源泄漏。 在托管 C++ 中,不存在 using 语句。 幸运的是,托管 C++ 足够强大,可以通过使用模板来扩展自身。 在本文中,我将解释一些关于资源管理的内容,以及如何将 using 语句引入 C++/CLI。

背景

公共语言运行时 (CLR) 是 .NET Framework 的基本组成部分,它执行所有 .NET 语言编译成的中间语言 (IL) 代码。 作为这些语言的基础,它也决定了语言能够提供的概念和功能的界限。 因此,CLR 仅提供常见的功能,并且不提供开箱即用的资源管理。 这将导致对所有其他基于它的语言的进一步限制。

幸运的是,.NET Framework 引入了一种资源管理模式。 这种模式提供了 IDisposable 接口。 它定义了封装资源的类型应该提供一个 Dispose 方法,以便在不再需要资源时释放资源。

与 C++ 不同,C# 是一种没有析构函数概念的语言。 因此,它使用 try-finallyusing 语句以可靠和安全的方式释放资源。 这意味着即使抛出异常,资源也会被释放。

// C# example of the using statement
 
using(DisposableObject MyDisposableObject = new DisposableObject())
{
    // usage of MyDisposableObject
}

using 语句在自己的作用域内创建一个对象。 如果执行超出作用域,则将调用对象的 Dispose 方法,这将导致释放资源。

Microsoft 使用 try-finally 语句扩展了托管 C++,但没有 using 语句。 现在,你可能会问自己,当有析构函数时,为什么我们需要 try-finally

那是因为托管 C++ 是建立在 CLR 之上的,而 CLR 没有析构函数的概念,因此会发生一些神奇的事情。 语言通过使用相同的语法来假装使用析构函数。 当代码编译成 IL 时,编译器会自动发出必要的 IL 代码来实现充当析构函数的 Dispose 方法。

正如您在图中看到的那样,对象实现了 IDisposable::Dispose 方法。 这就是为什么在 C++/CLI 中显式实现 Dispose 方法是不合法的。

Using the Code

接下来,我将向您展示一个引入 C++/CLI 中 using 语句的代码片段。 以下模板只做一件事;当模板本身被析构时,它会调用某个对象的析构函数。

// C++/CLI realization of the using statement
 
template <class T> ref class Using
{
private:
    T^ m_Handle;
 
public:
    Using(T^ Object)
    {
	m_Handle = Object;
    }
 
    T^ operator->()
    {
	return m_Handle;
    }
 
    ~Using()
    {
	delete m_Handle;
    }
};

在我解释它如何工作之前,我将举一个如何使用它的例子。

// C++/CLI usage of the introduced using statement
 
{
   Using<DisposableObject> MyDisposableObject(gcnew DisposableObject());
 
   // usage of MyDisposableObject
   MyDisposableObject->PrintCoolStuff();
}

这里发生了什么以及它是如何工作的?

如果您执行示例代码,将在堆栈上创建一个模板对象。 这意味着,当执行超出范围时,将调用模板对象的析构函数。 由于在堆上创建了 DisposableObject 的句柄,模板对象能够调用其 Dispose 方法以释放资源。 因为模板对象是在堆栈上创建的,所以它的析构函数也会在出现异常时被调用。 语句周围的括号用于定义 C++ 中的作用域。

如果您比较托管 C++ 和 C# 之间的这两个语句,您会认识到它们的相似之处。 我建议下载代码片段以进行进一步的探索。

关注点

对我来说,C++/CLI 是万能的 .NET 语言。 通过成为 CLR 的低级语言,它提供了很大的自由度。 通过使用模板来扩展语言不需要太多的努力。 你有没有注意到代码片段有多短?

历史

  • 2009 年 1 月 7 日 - 文章发表
© . All rights reserved.