科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Visual Studio 2005体验泛型编程

Visual Studio 2005体验泛型编程

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

Visual Studio 2005 为 Microsoft .NET 框架带来了泛型编程的类型参数化模型。

作者:许嵩罡编译 来源:VCKBASE 2007年11月16日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
什么是参数化的类型?

  类型参数模型提供了第二层隔离,消除了向下强制类型转换和框入/框出操作,并允许编译时同类容器元素类型冲突的降格(flagging)。它是一种两步解决方案。在第一步中,将一个类型参数当作一个 实际类型的占位符,就像函数所做的那样:

interface class IEnumerator
{
  property typeParameter Current { typeParameter get(); }
  bool MoveNext();
  void Reset();
}

  在第二步,你告诉编译器(程序的机器阅读器),typeParameter 是一个占位而不是一个程序实体。这一步是通过叫做参数化列表的泛型署名来完成的。在C++/CLI中, 要么引入 generic 关键字以选择公共语言运行时(CLR)泛型机制,要么引入 template 关键字以选择使用 C++ 模板类型机制。如 Figure 1 所示。

Figure 1 Indicating typeParameter
Generic Keyword
generic <typename typeParameter>
interface class IEnumerator
{
 property typeParameter Current { typeParameter get(); }
 ...
};

Template Keyword
template <typename typeParameter>
interface class IEnumerator
{
 property typeParameter Current { typeParameter get(); }
 ...
};

  这样便导致了一个类型无关的接口定义。之后,当某个类实现 IEnumerator 时,它必需提供一个实际的类型绑定到 typeParameter 占位 符。这是通过将括弧中实际的类型与参数化类名配对实现的,比如IEnumerator<int>

  C++/CLI 支持两种参数化类型机制,模板和泛型,用于定义参数化引用、值和接口类,函数和委托。从表面上看,参数化的 generic 和 template 至少在语句构成上是等同的(除了 template 或 generic 关键字有所不同)。而在其它方面,它们有显著的不同。

  考虑一下 Figure 2 中的两个栈声明,template 实例(tStack),通过标准模板库(STL)的 CLI 实现提供了一个使用动态 vector 容器的例子,以及 generic 实例(gStack),通过 System::Collections::Generic 名字空间提供的使用动态 List<T> 容器的例子。两者在 Visual Studio 2005 中都是新的参数化类型集合库。

Figure 2 Template and Generic Stack Declaration
C++/CLI Template Stack Declaration
#include <cliext/vector>
using namespace cliext;

template <class elemType>
ref class tStack
{
 // the CLI vector is a reference class …
 vector<elemType> ^m_stack;
 int top;

 public:
  tStack();
  elemType pop();
  void push( elemType et );
  ...
};

C++/CLI Generic Stack Declaration
using namespace System::Collections::Generic

generic <class elemType>
public ref class gStack {
 List<elemType> ^m_stack;
 int top;

 public:
  gStack();
  elemType pop();
  void push( elemType et );
  ...
};

  通过在类名后的尖括弧中指定实际类型来创建参数化类型实例。例如,Figure 3 依次示范了用整型和字符串类型参数实例化的 template 堆栈。为了创建等同的 generic 堆栈实例,Figure 4 所用的两种类型参数是相同的。

Figure 3 Instantiating the Template Stack
void demo_template_Stack()
{
 // an int value type argument...

 tStack<int>^ is = gcnew tStack<int>( 10 );
 for ( int ix = 0; ix < 10; ix++ )
  is->push( ix*2 );

 int elem_cnt = is->size();
 for ( int ix = 0; ix < elem_cnt; ++ix )
  Console::WriteLine( "({0}) {1}", ix+1, is->pop());

 // a String^ reference type argument...

 tStack<String^> ^ss = gcnew tStack<String^>( 10 );
 ss->push( "Pooh" ); ss->push( "Piglet" );
 ss->push( "Rabbit" ); ss->push( "Eeyore" );

 elem_cnt = ss->size();
 for ( int ix = 0; ix < elem_cnt; ++ix )
  Console::WriteLine( "({0}) {1}", ix+1, ss->pop());
}

Figure 4 Instantiating the Generic Stack

void demo_generic_Stack()
{
 // an int value type argument...

 gStack<int>^ is = gcnew gStack<int>( 10 );
 for ( int ix = 0; ix < 10; ix++ )
  is->push( ix*2 );

  int elem_cnt = is->size();
  for ( int ix = 0; ix < elem_cnt; ++ix )
   Console::WriteLine( "({0}) {1}", ix+1, is->pop());

   // a String^ reference type argument...

   gStack<String^> ^ss = gcnew gStack<String^>( 10 );
   ss->push( "Pooh" ); ss->push( "Piglet" );
   ss->push( "Rabbit" ); ss->push( "Eeyore" );

   elem_cnt = ss->size();
   for ( int ix = 0; ix < elem_cnt; ++ix )
   Console::WriteLine( "({0}) {1}", ix+1, ss->pop());
 }

  参数化类型对象的实际处理,例如 is 和 ss,与非参数化类型对象的处理完全一样。参数化类型的一个好处是单一的源定义能潜在地产生出无数种型实例。该例子中,generic 和 template 堆栈类在相同的参数化类源代码之外都支持字符串和整型类。在所有已知类型的应用程序中使用它们时没有真正的约束。正如你将会在后续专栏中看到的那样,并不是所有参数化类型都这样。

  generic 和 template 定义以及种型实例在这里几乎是等价的,尽管并不是所有的参数化类型都这样。或者说在支持两种机制的 C++/CLI 中益处不多。当我在后续专栏中详细讨论两种机制时,你会看到其它一些差异。正是存在这些差异,在我遇到它们时,将它突出出来,而不是反复说其共性,似乎是整合其全貌的更好方法。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章