转贴(天极论坛):代码换肤术——C#和VB

转载 2004年07月16日 16:09:00
转贴(天极论坛):代码换肤术——C#和VB

现在流行程序“换肤术”,就是把操作界面变个样子,程序当然还是原来的程序。代码的移植也可以称为一种“换肤术”,内容不改,但变成了另一种语言。本文介绍的是从当今最火热的C#与VB.net间移植的技巧。 
   
  按理说,这两种语言没有什么移植的必要,因为他们生成的代码可以完全通用。但是如果一个工程基本上是VB写成的,却需要少许已经存在的C#过程,用组件并不是一种效率很高的办法。就算是学习C#或VB,学会他们之间的移植可以双倍的利用已经存在的代码(如好玩的Donkey.net就只有VB版)。 
   
  有人比较过这两种语言,得出的结论是他们很相似。但即便是这样,VB初学者看到诸如((Button)sender).Text = “启动”;之类的语法不知道如何移植到VB,而C#初学者看到Handles Button1.Click等语法也会为移植而感到头痛。下面就看看他们最难移植的部分: 
   
  1、Option语句。VB的Option语句可以打开或关闭变量声明检查和类型转换检查。尤其是Option Strict被关闭后,VB变成弱类型语言,很多类型转换都是自动的,移植到C#中会产生无数错误。因此,如果要将带有Option Strict Off语句的VB程序移植到C#,最好先在VB中将Option Strict打开,然后把所有类型转换出错的地方变成强类型转换,然后再进行移植。 
   
  2、类型转换。VB提供了很多类型转换函数型运算符,如CInt(), CSng(), CStr()等,在C#中只要用(int) , (float), (String)即可。然而如果不是标准类型,如下面的C#语句: 
   
  ((System.Button)sender).Text = “启动”; 
   
  就要使用VB的函数型运算符CType来实现。上面的代码正确的移植方法是: 
   
  CType(sender, System.Button).Text = “启动” 
   
  千万不要使用某些人推荐的,将Option Strict关闭,然后用后期绑定调用sender对象的方法,这根本不符合程序移植不能改变本质的要求。 
   
  3、修饰符和属性标签。VB和C#的修饰符是完全对等存在的,但是拼写往往不同,给移植带来了很多麻烦,尤其是表示相同意思的关键字从字面理解完全不同的时候。下面就给出了VB和C#对应的关键字: 
   
  VB 
   C# 
   VB 
   C# 
   
  Inherits 
   : 
   Implements 
   : 
   
  MustInherit 
   abstract 
   NotInheritable 
   sealed 
   
  Overridable 
   virtual 
   NotOverridable 
   sealed 
   
  MustOverride 
   abstract 
   Overrides 
   override 
   
  [Overloads] 
   无 
   Shadows 
   new 
   
  Shared 
   static 
   Public 
   public 
   
  Protected 
   protected 
   Friend 
   internal 
   
  Protected Friend 
   protected internal 
   Private 
   private 
   
  Static 
   用别的方法实现 
   ByVal 
   无 
   
  ByRef 
   ref 
   Optional 
   无 
   
  ParamArray 
   params 
   无法实现 
   unsafe 
   
  无法实现 
   fixed 
   
   
  可以看出,VB的关键字比较长,而且使用上也比C#更加严格。从C#向VB移植的时候,要分外注意哪些VB有而C#没有的关键字以及在C#拼写相同,在VB中拼写不同的关键字(如MustOverride和MustInherit)。有些关键字如unsafe,如果C#使用了他们,将无法移植到VB中。好在这些关键字在商业应用中并不常用。 
   
  属性标签在这两种语言中非常的相似,移植上应该没有任何难度,只要知道在C#中用方括号[]表示属性标签,而在VB中用的是尖括号<>。另外,如果要用名称结合传递参数,C#直接使用=号,而VB使用:=(冒号和等号)。 
   
  4、委派类型。委派类型就是安全的函数指针类型。在C#中,难以分辨是函数指针在工作还是函数本身在工作,因为他们的语法相同。当要为一个委派类型的变量复制的时候,直接等于一个函数即可,如: 
   
  public delegate void FuncType(Object e) 
   
  ... 
   
  FuncType func; 
   
  func = new FuncType(this.SampleFunction1); 
   
  //调用 
   
  func(something); 
   
  //换指向另外一个函数 
   
  func = this.SampleFunction2 
   
  然而VB中,委派类型就像是一般的对象,有它的方法,与函数本身明显不同。你不能将过程的名字直接赋给一个委派类型的对象,而必须使用AddressOf运算符,下面的例子就是上文C#程序的VB版,注意那些实现不同的地方: 
   
  Public Delegate Sub FuncType(ByVal e As Object) 
   
  ... 
   
  Dim func As FuncType 
   
  func = New FuncType(AddressOf Me.SampleFunc1) 
   
  ‘ 调用 
   
  func.Invoke(something) 
   
  ‘ 换指向另外一个函数 
   
  func = AddressOf Me.SampleFunction2 
   
  5、事件处理。这是两种语言最大的差别之一,VB传承以前版本强大的事件处理机制,许多语法都比C#更加灵活。好在无论什么情况,他们之间都是可以互相移植的。 
   
  对于事件定义,两种语言都是一个委派类型加一个事件属性,如: 
   
  [C#] 
   
  public delegate void MyEventHandler(Object sender, EventArgs e); 
   
  public event MyEventHandler MyEvent; 
   
  [Visual Basic] 
   
  Public Delegate Sub MyEventHandler(ByVal sender As Object, ByVal e As EventArgs) 
   
  Public Event MyEvent As MyEventHandler 
   
  VB还支持另外一种更加紧凑的定义方法,只有一条语句: 
   
  Public Event MyEvent(ByVal sender As Object, ByVal e As EventArgs) 
   
  移植的时候,要把参数部分分离出来,成为一个委派类型,再按照普通方法定义事件即可。 
   
  关于事件响应,C#与Delphi等语言一样,是动态绑定事件过程的,其语法类似于下: 
   
  internal MyClass myobj; 
   
  ... 
   
  myobj = new MyClass(); 
   
  ... 
   
  myobj.MyEvent += this.myobj_MyEvent; 
   
  ... 
   
  protected void myobj_MyEvent(Object sender, EventArgs e) 
   
  { 
   
   //语句 
   
  } 
   
  可以看到,C#是利用运算符连接事件过程和事件属性的。之后,还可以用-=运算符解除事件过程与事件属性的绑定。VB不支持运算符重载,但仍然支持这种动态绑定的事件过程,方法是使用AddHandler和RemoveHandler关键字。如上面黑体部分可以移植为: 
   
  AddHandler myobj.MyEvent, AddressOf Me.myobj_MyEvent 
   
  解除绑定的语法与此类似,只是关键字为RemoveHandler而已。一定不要忘记过程前面还有一个AddressOf关键字! 
   
  动态绑定的事件过程工作起来比较慢,VB支持一种更快的静态绑定事件过程。一旦为对象设置了静态的事件过程,就不能解除绑定,一般大多数情况都是如此。语法如下: 
   
  ‘ 定义变量时使用WithEvents关键字 
   
  Friend WithEvents myobj As MyClass 
   
  ‘ 直接书写事件过程,注意Handles的语法: 
   
  Protected Sub myobj_MyEvent(ByVal sender As Object, ByVal e As EventArgs) _ 
   
  Handles myobj.MyEvent 
   
   ‘ 语句 
   
  End Sub 
   
  它表示myobj_MyEvent这个过程仅仅响应myobj.MyEvent这个过程。如果一个过程要响应很多个事件,把他们列在Handles后面,用逗号隔开,如Handles Event1, Event2, ... 
   
  遇到这种情况,要看清Handles后面的所有对象和事件,将它们一一改写成动态绑定的语句: 
   
  Protected Sub XXX(...) Handles myobj1.MyEvent, myobj2.MyEvent 
   
  ==> 
   
  myobj1.MyEvent += this.XXX; 
   
  myobj2.MyEvent += this.XXX; 
   
  ... 
   
  protected void XXX(...){} 
   
  当事件比较多时,C#显著变得比较麻烦,幸好一个过程响应一大堆事件的情况也不太多(不过我就编写过一个过程相应8个事件,移植起来好麻烦!)。原则上说,将静态事件过程移植为动态事件过程并没有完全遵守移植的规定,但我估计他们实现的原理不会相差太多,所以也不用担心。 
   
  6、异常处理。VB支持两种形式的异常,即.net框架的异常和VB自己的错误号码。而C#只支持第一种。用到VB自己的错误号码的程序几乎无法移植到C#中,所以应该尽量使用.net框架的异常,如下面VB语句: 
   
  Try 
   
   ‘ 发生错误的代码 
   
  Catch When Err.Number = 52 
   
   ‘ 解决错误的代码 
   
  End Try 
   
  这段代码无法直接移植到C#中,只有用Exception对象取代Err对象获得异常信息,才能顺利移植。另外VB的When语句带给Try语句十分灵活的用法,必须用很高的技巧才能在C#中实现,这就需要具体问题具体分析了。 
   
  VB支持Exit Try语句,可以直接从Try块或Catch块跳转到Finally块。C#没有提供类似的语法,可以用以下技巧: 
   
  [Visual Basic] 
   
  Try 
   
   ‘ 一些语句 
   
   Exit Try 
   
  Finally 
   
   ‘ 一些语句 
   
  End Try 
   
  [C#] 
   
  try 
   
  { 
   
   //一些语句 
   
   goto __leave; 
   
  } 
   
  finally 
   
  { 
   
   //一些语句 
   
  } 
   
  __leave: //别忘了这里还有哦! 
   
  总之是利用了finally块无法跳过的特征,用goto语句模拟了Exit Try语句。 
   
  如果VB程序用的是VB特有的On Error GoTo语句实现的错误处理,问题就麻烦了。代码可能在过程中上下跳跃,无法预料语句的执行方式。这种代码理解起来就头痛,更不要说移植了。总体来说,把所有语句统统转移到try块中,然后用catch一一处理错误。遇到要返回(Resume语句)的时候,只好Copy代码了。反正不是一件容易的事情,慢慢改就是了。 
   
  7、模块。VB支持模块,C#不支持。但也没有关系,只要在C#中制造一个abstract类,共享所有成员,就和模块一样了。当然不能像VB一样直接访问模块中的成员,需要用到“类名.成员名”的用法。 
   
  8、接口。C#在接口方面也没有VB强大(怎么这么重要的功能也不做得好一点?),VB采用Implements语句结合接口的成员和类的实现成员,而C#是用名称结合。因此VB就可以随便修改实现成员的访问级别和名称,而C#就不能改名称。将C#移植为VB时,最好利用VB.net编辑器直接实现接口,比较简单。把VB移植为C#时,就必须把改过的名字都改回来,遇到名字冲突就更讨厌了(这时候我几乎不想再移植为C#了)。给一个例子: 
   
  [Visual Basic] 
   
  Public Class Class1 : Implements IMyInterface 
   
   Public Sub DoSth() Implements IMyInterface.Method1 
   
   End Sub 
   
  End Class 
   
  [C#] 
   
  public class Class1 : IMyInterface 
   
  { 
   
   public void Method1() 
   
  { 
   
  } 
   
  } 
   
  9、运算符重载。这会遇到VB头痛了,既然VB不支持运算符重载,那么就必须用子程序和函数来模拟运算符。比如建立Plus和Minus方法模拟+和-的运算。当然还是有很多情况(比如遇上了explicit和implicit语句)就真的没有办法了,只好不移植了。运算符重载是一个很不错的功能,它能使很多操作简单地完成,如果VB支持它,就真的是完美语言了。 
   
  好了,想必最麻烦的地方已经说完了,剩下的就是简单的Copy了。虽然有些地方还没有说清楚,但基本上阐明了两种语言的不同(一看,不同还挺多的吧),反正也不用移植大的工程,了解这些内容主要是为了利用双倍的利用已经存在的代码,但愿本文对你有用。由于水平低劣,如有错误请各位大虾指正,小弟必洗耳恭听。 

C#界面美化之换肤

C#界面更加美观
  • PanPen120
  • PanPen120
  • 2015年03月27日 20:08
  • 1779

将C++转换成VB,C#语言小工具介绍

在网上看到很多网友在.NET程序中调用Win32 API,或者调用自己的VC DLL里面提供的函数的时候,总是被生成正确的C函数在C#中的正确声明而困扰,而生成C++中结构体在C#中的声明 - 天,没...
  • shejiannan
  • shejiannan
  • 2014年05月22日 11:39
  • 2001

用割圆术求圆周率π

以半径为1的圆开始,依次在圆内画正六边形、正十二边形、正6n边形...。      只有n趋近于无穷大,便可以得到足够接近圆的多边形,计算的圆周率π也就越精确。 完整代码如下:...
  • sanqima
  • sanqima
  • 2014年06月12日 09:28
  • 1720

【C#】—vb和c#实现对比

前两篇文章都是写的关于c#的概念性的东西,在学习敲了几章设计模式中的例子后,真是的感觉到和自己之前总结的有所不同。然后又结合vb功能实现和c#功能实现在总结下。     一、vb功能实现。 ...
  • u013036959
  • u013036959
  • 2014年12月07日 11:50
  • 2240

C# 轻松实现对窗体(Form)换肤

一直想写一个比较完整的、容易扩展的窗体换肤的方案,由于时间问题,都没去实现这个想法。现在有朋友提出需要,就把以前写的重新拿出来看了一篇,花了些时间,做出了现在的这个换肤的方案。实现的过程中遇到了不少问...
  • blacksource
  • blacksource
  • 2013年12月26日 10:05
  • 4083

仿造百度换肤功能的实现

换肤功能的应用很广,不管是搜索界面还是普通的管理界面等等,都可以进行设计并且应用换肤功能,起到更好的用户体验。 今天仿造百度的换肤功能,实现了基本的换肤功能,接下来将会为大家介绍如何实现。在设计界...
  • u010297791
  • u010297791
  • 2016年09月14日 09:17
  • 1634

js利用cookie实现网页的换肤

在浏览网页的时候,我们经常可以看到部分页面上具有换肤功能,点击改变皮肤且但我们下次浏览的时候,还会是我们选择的皮肤。作为菜鸟来说,这是一种赤裸裸的诱惑……今天查了相关资料,很粗糙的写了一个利用cool...
  • u014703834
  • u014703834
  • 2014年07月31日 16:32
  • 1371

VB / Java / C / C# / C++ 等零基础学哪个更容易上手?

不同的编程语言有着不同的抽象层次, 有些更偏向硬件的工作原理,有些更贴近人类的思维方式。以Python和C为例,Python更像英语,基本的思维方式也更类似自然语言,而C则更类似于计算机硬件本身的工...
  • baidu_35738377
  • baidu_35738377
  • 2016年11月04日 10:04
  • 403

JS网页换肤读取cookie基础案例

JS网页换肤读取cookie基础案例
  • qq_20266611
  • qq_20266611
  • 2016年09月02日 11:28
  • 146

VB和C#中循环语句

引言:学习了C#的循环语句,让我觉得有点吃力,其实从原理上讲这些是学过的,只是没有对比着来,现在把他们放在一起,发现其实真的是一样的,这样学习起来就容易了很多,给自己减少了很多压力。         ...
  • wxr15732623310
  • wxr15732623310
  • 2015年11月29日 18:46
  • 1046
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:转贴(天极论坛):代码换肤术——C#和VB
举报原因:
原因补充:

(最多只允许输入30个字)