网站推广,网站提供网站推广、免费网络推广、网络推广研究、网络推广、免费网站推广、网络推广培训、网络推广软件、网络推广工具、交换连接、行业网站推广、地域网站推广,提供功能强大的免费推广服务.

由c++转向c#需要注意的变化(六)


引言:每隔10年左右,编程人员就需要花费大量的时间和精力去学习新的编程技术。在80年代是unix和c,90年代是windows和c++,现在又轮到了微软的.netframework和c#。尽管需要学习新的技术,但由此带来的好处却远高于付出的劳动。幸运的是,使用c#和.net进行的大多数工程的分析和设计与在c++和windows中没有本质的变化。在本篇文章中,我将介绍如何实现由c++到c#的飞跃。
  已经有许多文章介绍过c#对c++的改进,在这里我就不再重复这些问题了。在这里,我将重点讨论由c++转向c#时最大的变化:由不可管理的环境向可管理的环境的变化。此外,我还会提出一些c#编程人员容易犯的错误供大家参考,此外,还将说明一些c#语言的能够影响编程的新功能。
  系列文章:[由c++转向c#需要注意的变化(一)(二)(三)(四)(五)]
  只发现方法
  我们可能会只关心方法,而不关心域、属性等,为此,我们需要删除如下的对getmembers的调用:


  memberinfo[]mbrinfoarray=
  thetype.getmembers(bindingflags.lookupall);  

  然后添加调用getmethods的语句:

  mbrinfoarray=thetype.getmethods();  

  现在,输出中就只剩下方法了。

  output(excerpt)
  booleanequals(system.object)isamethod
  system.stringtostring()isamethod
  system.stringcreatequalifiedname(system.string,system.string)
  isamethod
  system.reflection.methodinfoget_entrypoint()isamethod  

  发现特定的成员
  最后,为了进一步地缩小范围,我们可以使用findmembers方法来发现某一类型的特定的方法。例如,在下面的代码中,我们可以只搜索以“get”开头的方法。

  publicclasstester
  {
  publicstaticvoidmain()
  {
  //检查一个单一的对象
  typethetype=type.gettype("system.reflection.assembly");
  //只获取以get开头的成员
  memberinfo[]mbrinfoarray
  thetype.findmembers(membertypes.method,
  bindingflags.default,
  type.filtername,"get*");
  foreach(memberinfombrinfoinmbrinfoarray)
  {
  console.writeline("{0}isa{1}",
  mbrinfo,mbrinfo.membertype.format());
  }
  }
  }

  其输出的一部分如下所示:

  system.type[]gettypes()isamethod
  system.type[]getexportedtypes()isamethod
  system.typegettype(system.string,boolean)isamethod
  system.typegettype(system.string)isamethod
  system.reflection.assemblynamegetname(boolean)isamethod
  system.reflection.assemblynamegetname()isamethod
  int32gethashcode()isamethod
  system.reflection.assemblygetassembly(system.type)isamethod
  system.typegettype(system.string,boolean,boolean)isamethod  

  动态调用
  一旦发现一个方法,可以使用映射的方法调用它。例如,我们可能需要调用system.math中的cos方法(返回一个角的余弦值)。为此,我们需要获得system.math类的类型信息,如下所示:

  typethemathtype=type.gettype("system.math");  

  有了类型信息,我们就可以动态地加载一个类的实例:

  objecttheobj=activator.createinstance(themathtype);  

  createinstance是activator类的一个静态方法,可以用来对对象进行初始化。
  有了system.math类的实例后,我们就可以调用cos方法了。我们还需要准备好一个定义参数类型的数组,因为cos只需要一个参数(需要求余弦值的角度),因此数组中只需要有一个成员。我们将在数组中赋予一个system.double类型的type对象,也就是cos方法需要的参数的类型:

  type[]paramtypes=newtype[1];
  paramtypes[0]=type.gettype("system.double");  

  现在我们就可以传递方法的名字了,这个数组定义了type对象中getmethod方法的参数的类型:

  methodinfocosineinfo=
  themathtype.getmethod("cos",paramtypes);  

  我们现在得到了methodinfo类型的对象,我们可以在其上调用相应的方法。为此,我们需要再次在数组中传入参数的实际值:

  object[]parameters=newobject[1];
  parameters[0]=45;
  objectreturnval=cosineinfo.invoke(theobj,parameters);  

  需要注意的是,我创建了二个数组,第一个名字为paramtypes的数组存储着参数的类型,第二个名字为parameters的数组保存实际的参数值。如果方法需要二个参数,我们就需要使这二个数组每个保持二个参数。如果方法不需要参数,我们仍然需要创建这二个数组,只是无需在里面存储数据即可。

  type[]paramtypes=newtype[0];  

  尽管看起来有点奇怪,但它是正确的。下面是完整的代码:
  映射方法的使用

  usingsystem;
  usingsystem.reflection;publicclasstester
  {
  publicstaticvoidmain()
  {
  typethemathtype=type.gettype("system.math");
  objecttheobj=activator.createinstance(themathtype);
  //只有一个成员的数组
  type[]paramtypes=newtype[1];
  paramtypes[0]=type.gettype("system.double");
  //获得cos()方法的信息
  methodinfocosineinfo=
  themathtype.getmethod("cos",paramtypes);
  //将实际的参数填写在一个数组中
  object[]parameters=newobject[1];
  parameters[0]=45;
  objectreturnval=cosineinfo.invoke(theobj,parameters);
  console.writeline(
  "thecosineofa45degreeangle{0}",returnval);
  }
  }


  结论
  尽管有许多小错误等着c++编程人员去犯,但c#的语法与c++并没有太大的不同,向新语言的转换是相当容易的。使用c#的有趣的部分是使用通用语言运行库,这篇文章只能涉及几个重点问题。clr和.netframework提供了对线程、集合、互联网应用开发、基于windows的应用开发等方面提供了更多的支持。语言功能和clr功能之间的区分是非常模糊的,但组合在一起就是一种功能非常强大的开发工具了。