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

VB.NET 和 C# 完全对比

2005年3月30日

11分钟阅读

viewsIcon

1610580

本文解释了 VB.NET 和 C# 的优点、区别和新特性。

目录

  1. 引言
  2. 两种语言的优点
  3. 关键字区别
  4. 数据类型区别
  5. 运算符区别
  6. 编程区别
  7. 2005年版本中两种语言的新特性
  8. 结论
  9. 历史

引言

有些人喜欢 VB.NET 的自然语言、不区分大小写的方法,而另一些人则喜欢 C# 的简洁语法。但两者都可以访问相同的框架库。我们将在以下主题中讨论这些区别:

  1. 两种语言的优点
  2. 关键字区别
  3. 数据类型区别
  4. 运算符区别
  5. 编程区别

两种语言的优点

VB.NET

C#

  • 支持可选参数——这对于某些 COM 互操作非常有用。
  • 支持带 Option Strict off 的后期绑定——编译时类型安全将不复存在,但使用没有强类型接口的遗留库会更容易。
  • 支持命名索引器。
  • 各种遗留 VB 函数(在 Microsoft.VisualBasic 命名空间中提供,并且其他语言可以通过引用 Microsoft.VisualBasic.dll 来使用)。然而,如果不当使用,其中许多函数可能会损害性能,而且许多人认为应在很大程度上避免使用它们。
  • with 构造:这是有利还是弊,尚有争议,但它确实是一个区别。
  • 更简单的(表达上——可能理解上更复杂)事件处理,其中一个方法可以声明它处理一个事件,而不是在代码中设置处理程序。
  • 以不同名称的方法实现接口的能力。(但有人认为这使得查找接口实现更困难。)
  • Catch ... When ... 子句,允许根据运行时表达式而不是仅按类型来过滤异常。
  • Visual Studio .NET 的 VB.NET 部分会在后台编译你的代码。虽然这对于小型项目来说被认为是一个优势,但创建非常大型项目的开发人员发现,随着项目变大,IDE 的速度会显著变慢。
  • 从源代码注释生成的 XML 文档。(这将在 VB.NET 的 Whidbey 版本(Visual Studio 和 .NET 下一个版本的代号)中出现,并且已经有工具可以处理现有的 VB.NET 代码。)
  • 运算符重载——同样,将在 VB.NET 的 Whidbey 版本中加入。
  • 语言对无符号类型的支持(你可以从 VB.NET 中使用它们,但它们本身并不在语言中)。同样,在 Whidbey 版本中 VB.NET 将支持这些。
  • using 语句,它使非托管资源处理变得简单。
  • 显式接口实现,其中一个基类已实现的接口可以在派生类中单独重新实现。有人认为这使得类更难理解,就像成员隐藏通常那样。
  • 不安全代码。它允许指针算术等,并在某些情况下提高性能。但是,不应轻易使用,因为 C# 的许多正常安全性(顾名思义)会丢失。请注意,不安全代码仍然是托管代码,即它被编译为 IL,经过 JIT 编译,并在 CLR 中运行。

关键字区别

目的

VB.NET

C#

声明变量

Private, Public, Friend, Protected, Static1, Shared, Dim

declarators(关键字包括用户定义类型和内置类型)

声明命名常量

Const

const

创建新对象

New, CreateObject()

new

函数/方法不返回值

Sub

void

重载函数或方法(Visual Basic:重载过程或方法)

Overloads

(此目的无需语言关键字)

引用当前对象

this

对当前对象的虚拟方法进行非虚拟调用

MyClass

不适用

从字符串中检索字符

GetChar Function

[]

声明复合数据类型(Visual Basic:Structure)

Structure <members> End Structure

struct, class, interface

初始化对象(构造函数)

Sub New()

构造函数,或系统默认类型构造函数

直接终止对象

不适用

不适用

垃圾回收回收对象前系统调用的方法7

最终化

析构函数

在声明处初始化变量

Dim x As Long = 5
Dim c As New _
   Car(FuelTypeEnum.Gas)

// initialize to a value:
int x = 123;
// or use default 
// constructor:
int x = new int();

获取函数地址

AddressOf (对于类成员,此运算符返回一个函数引用,形式为一个委托实例)

delegate

声明对象可以异步修改

不适用

volatile

强制显式声明变量

Option Explicit

n/a. (所有变量必须在使用前声明)

测试不指向对象的对象变量

obj = Nothing

obj == null

不指向对象的对象变量的值

null

测试数据库 null 表达式

IsDbNull

不适用

测试 Variant 变量是否已初始化

不适用

不适用

定义默认属性

默认值

通过使用索引器

引用基类

MyBase

base

声明接口

接口

接口

指定要实现的接口

Implements (语句)

class C1 : I1

声明类

Class <implementation>

指定类只能继承。无法创建类的实例。

MustInherit

abstract

指定类不能被继承

NotInheritable

sealed

声明枚举类型

Enum <members> End Enum

enum

声明类常量

Const

const (应用于字段声明)

从基类派生类

Inherits C2

class C1 : C2

重写方法

Overrides

override

声明必须在派生类中实现的函数

MustOverride

abstract

声明不能被重写的方法

NotOverridable (方法默认不 overridable。)

sealed

声明虚拟方法、属性(Visual Basic)或属性访问器(C#、C++)

Overridable

virtual

在派生类中隐藏基类成员

隐藏

不适用

声明对类方法的类型安全引用

委托

delegate

指定一个变量可以包含一个你想处理其事件的对象

WithEvents

(编写代码 - 无特定关键字)

指定将调用事件过程的事件

Handles (事件过程仍然可以通过命名模式与 WithEvents 变量关联。)

不适用

评估一次对象表达式,以便访问多个成员

With objExpr 
  <.member>
  <.member> 
End With

不适用

结构化异常处理

Try <attempt>
Catch
<handle errors>
Finally
<always execute>
End Try

try, catch, finally, throw

决策结构(选择)

Select Case ..., Case, Case Else, End Select

switch, case, default, goto, break

决策结构(if ... then)

If ... Then, ElseIf ... Then, Else, End If

if, else

循环结构(条件)

While, Do [While, Until] ..., Loop [While, Until]

do, while, continue

循环结构(迭代)

For ..., [Exit For], Next
For Each ..., [Exit For,] Next

for, foreach

声明数组

Dim a() As Long

int[] x = new int[5];

初始化数组

Dim a() As Long = {3, 4, 5}

int[] x = new int[5] {
        1, 2, 3, 4, 5};

重新分配数组

Redim

不适用

项目或程序集外可见

Public

public

程序集外不可见(C#/Visual Basic)或包内不可见(Visual J#、JScript)

Friend

internal

仅在项目内可见(对于嵌套类,在包含类内)

Private

私有的

类和项目或模块外部可访问

Public

public

类外部、项目内部可访问

Friend

internal

仅类或模块内部可访问

Private

私有的

仅当前类和派生类可访问

Protected

受保护的

保留过程的局部变量

静态

不适用

由类的所有实例共享

共享

static

注释代码

'
Rem

//, /* */ 用于多行注释
/// 用于 XML 注释

区分大小写?

调用 Windows API

Declare <API>

使用 Platform Invoke

声明和引发事件

Event, RaiseEvent

事件

线程原语

SyncLock

lock

跳转到

Goto

goto

数据类型区别

目的/大小

VB.NET

C#

十进制

十进制

decimal

日期

日期

日期时间

(变化)

字符串

字符串

1 字节

字节型

byte

2 字节

布尔值

bool

2 字节

Short, CharUnicode 字符)

short, char (Unicode 字符)

4 字节

整数

int

8 字节

长整型

long

4 字节

Single

float

8 字节

双精度浮点型

double

运算符区别

目的

VB.NET

C#

整数除法

\

/

模运算(仅返回余数的除法)

Mod

%

求幂

^

不适用

整数除法赋值

\=

/=

字符串连接

&= NEW

+=

模运算

不适用

%=

按位与

不适用

&=

按位异或

不适用

^=

按位或

不适用

|=

等于

=

==

不等于

<>

!=

比较两个对象引用变量

Is

==

比较对象引用类型

TypeOf x Is Class1

x is Class1

连接字符串

&

+

短路布尔与

AndAlso

&&

短路布尔或

OrElse

||

作用域解析

.

.base

数组元素

()

[ ]

类型转换

Cint, CDbl, ..., CType

(类型)

后缀增量

不适用

++

后缀减量

不适用

--

间接寻址

不适用

* (仅限不安全模式)

取址

AddressOf

& (仅限不安全模式;另请参阅 fixed)

逻辑非

!

按位非(一的补码)

~

前缀增量

不适用

++

前缀减量

不适用

--

类型大小

不适用

sizeof

按位与

并且

&

按位异或

Xor

^

按位或

或者

|

逻辑与

并且

&&

逻辑或

或者

||

Conditional

If Function ()

?:

成员指针

不适用

. (仅限不安全模式)

编程区别

目的

VB.NET

C#

声明变量

Dim x As Integer
Public x As Integer = 10
int x;
int x = 10;

注释

' comment
x = 1  ' comment
Rem comment
// comment
/* multiline
 comment */

赋值语句

nVal = 7
nVal = 7;

条件语句

If nCnt <= nMax Then
   ' Same as nTotal = 
   ' nTotal + nCnt.
   nTotal += nCnt  
   ' Same as nCnt = nCnt + 1.
   nCnt += 1       
Else
   nTotal += nCnt
   nCnt -= 1       
End If
if (nCnt <= nMax)
{
   nTotal += nCnt;
   nCnt++;
}
else
{
   nTotal +=nCnt;
   nCnt--;
}

选择语句

Select Case n
   Case 0
      MsgBox ("Zero")  
     ' Visual Basic .NET exits
     ' the Select at 
     ' the end of a Case.
   Case 1
      MsgBox ("One")
   Case 2 
      MsgBox ("Two")
   Case Else
      MsgBox ("Default")
End Select



switch(n) 
{
   case 0:
      Console.WriteLine("Zero");
      break;
   case 1:
      Console.WriteLine("One");
      break;
   case 2:
      Console.WriteLine("Two");
      break;
   default:
      Console.WriteLine("?");
      break;
}

FOR 循环

For n = 1 To 10 
   MsgBox("The number is " & n)
Next

For Each prop In obj
    prop = 42
Next prop
for (int i = 1; i <= 10; i++) 
   Console.WriteLine(
      "The number is {0}", i);
foreach(prop current in obj)
{
   current=42;
}

隐藏基类成员

Public Class BaseCls
   ' The element to be shadowed
   Public Z As Integer = 100   
   public Sub Test()
      System.Console.WriteLine( _
        "Test in BaseCls")
   End Sub
End Class

Public Class DervCls
   Inherits BaseCls
   ' The shadowing element.
   Public Shadows Z As String = "*"
   public Shadows Sub Test()
      System.Console.WriteLine( _
          "Test in DervCls")
   End Sub
End Class

Public Class UseClasses
  ' DervCls widens to BaseCls. 
  Dim BObj As BaseCls = 
          New DervCls()
  ' Access through derived 
  ' class.
  Dim DObj As DervCls = 
       New DervCls()

  Public Sub ShowZ()
    System.Console.WriteLine( _
     "Accessed through base "&_
     "class: "  & BObj.Z)
    System.Console.WriteLine(_
    "Accessed through derived "&_
    "class: " & DObj.Z)
    BObj.Test()
    DObj.Test()
  End Sub 
End Class




public class BaseCls
{
   // The element to be hidden
   public int Z = 100;   
   public void Test()
   {
      System.Console.WriteLine(
        "Test in BaseCls");
   }
}

public class DervCls : BaseCls
{
  // The hiding element
  public new string Z = "*";   
  public new void Test()
  {
    System.Console.WriteLine(
      "Test in DervCls");
  }
}

public class UseClasses
{
  // DervCls widens to BaseCls
  BaseCls BObj = new DervCls();  
   // Access through derived 
   //class 
  DervCls DObj = new DervCls();  
  public void ShowZ()
  {
    System.Console.WriteLine(
    "Accessed through " +
      "base class: {0}", 
      BObj.Z);
    System.Console.WriteLine(
    "Accessed through" +
      " derived class:{0}",
      DObj.Z);
    BObj.Test();
    DObj.Test();
   }
}

WHILE 循环

' Test at start of loop
While n < 100 .
   ' Same as n = n + 1.
   n += 1     
End While '
while (n < 100)
   n++;
  

 

按值传递参数

' The argument Y is 
'passed by value.
Public Sub ABC( _
  ByVal y As Long) 
'If ABC changes y, the
' changes do not affect x.
End Sub
   
ABC(x) ' Call the procedure.
' You can force parameters to 
' be passed by value, 
' regardless of how 
' they are declared, 
' by enclosing 
' the parameters in 
' extra parentheses.
ABC((x))
/* Note that there is 
no way to pass reference 
types (objects) strictly 
by value. You can choose 
to either pass the reference 
(essentially a pointer), or 
a reference to the reference 
(a pointer to a pointer).*/
// The method:
void ABC(int x)
{
   ...
}
// Calling the method:
ABC(i);

按引用传递参数

Public Sub ABC(ByRef y As Long) 
' The parameter y is declared 
'by referece:
' If ABC changes y, the changes are
' made to the value of x.
End Sub

ABC(x) ' Call the procedure.












/* Note that there is no
 way to pass reference types 
 (objects)  strictly by value.
 You can choose to  either 
 pass the reference 
 (essentially  a pointer), 
 or a reference to the 
 reference (a pointer to a 
 pointer).*/
// Note also that unsafe C# 
//methods can take pointers 
//just like C++ methods. For 
//details, see unsafe.
// The method:
void ABC(ref int x)
{
   ...
}
// Calling the method:
ABC(ref i);

结构化异常处理

Try
   If x = 0 Then
      Throw New Exception( _
         "x equals zero")
   Else
      Throw New Exception( _
        "x does not equal zero")
   End If
Catch err As System.Exception
   MsgBox( _
   "Error: " & Err.Description)
Finally
   MsgBox( _
   "Executing finally block.")
End Try








// try-catch-finally
try
{
  if (x == 0)
   throw new System.Exception(
     "x equals zero");
  else
   throw new System.Exception(
     "x does not equal zero");
}
catch (System.Exception err)
{
  System.Console.WriteLine(
              err.Message);
}
finally
{
  System.Console.WriteLine(
   "executing finally block");
}



将对象引用设置为 Nothing

o = Nothing
o = null;

初始化值类型

Dim dt as New System.DateTime( _
  2001, 4, 12, 22, 16, 49, 844)


System.DateTime dt = 
 new System.DateTime(
 2001, 4, 12, 22, 16, 
      49, 844);

2005年版本中两种语言的新特性

VB.NET

C#

Visual Basic 2005 拥有许多新的和改进的语言特性——例如继承、接口、重写、共享成员和重载——使其成为一种强大的面向对象编程语言。作为 Visual Basic 开发人员,您现在可以使用显式的多线程来创建多线程、可扩展的应用程序。该语言具有以下新特性:

  1. Continue 语句,它立即跳到 DoForWhile 循环的下一次迭代。
  2. IsNot 运算符,您可以使用它来避免以一种尴尬的顺序使用 NotIs 运算符。
  3. 3. Using...EndUsing 语句块确保在您的代码因任何原因离开该块时,系统资源得到释放。
    Public Sub setbigbold( _
        ByVal c As Control)
    Using nf As New _
      System.Drawing.Font("Arial",_
      12.0F, FontStyle.Bold)
      c.Font = nf
      c.Text = "This is" &_
      "12-point Arial bold"
    End Using
    End Sub
  4. 数组的显式零下界,Visual Basic 现在允许数组声明在指定上界的同时指定每个维度的下界(0)。
  5. 无符号类型,Visual Basic 现在支持无符号整数数据类型(UShortUIntegerULong)以及有符号类型 SByte
  6. 运算符重载,Visual Basic 现在允许您在已定义的类或结构上定义标准运算符(如 +&NotMod)。
  7. 部分类型,将生成代码与您编写的代码分开到不同的源文件中。
  8. Visual Basic 现在支持泛型类、结构、接口、过程和委托的类型参数。相应的类型参数在编译时指定泛型类型中一个元素的类型。
  9. 自定义事件。您可以使用 `Custom` 关键字作为 `Event` 语句的修饰符来声明自定义事件。在自定义事件中,您可以精确地指定当代码将事件处理程序添加到事件或从中移除时,或者当代码引发事件时会发生什么。
  10. 编译器检查选项,`/nowarn` 和 `/warnaserror` 选项提供了对警告处理的更多控制。每个编译器选项现在都接受一个可选的警告 ID 列表作为参数,以指定选项适用的警告。
  11. 有八个新的命令行编译器选项:
    1. `/codepage` 选项指定打开源文件时使用的代码页。
    2. `/doc` 选项根据代码中的注释生成 XML 文档文件。
    3. `/errorreport` 选项提供了一种方便的方式,可以通过 Internet 将 Visual Basic 内部编译器错误报告给 Microsoft。
    4. `/filealign` 选项指定输出文件中的节大小。
    5. `/noconfig` 选项使编译器忽略 `Vbc.rsp` 文件。
    6. `/nostdlib` 选项阻止导入定义整个 System 命名空间的 `mscorlib.dll`。
    7. `/platform` 选项指定输出文件的目标处理器,在需要显式指定的情况下。
    8. `/unify` 选项抑制因直接和间接引用的程序集版本不匹配而产生的警告。

随着 Visual Studio 2005 的发布,C# 语言已更新到 2.0 版本。该语言具有以下新特性:

  1. 泛型类型已添加到语言中,以使程序员能够为集合类实现高度的代码重用和增强的性能。泛型类型仅在元数上有所不同。参数也可以强制为特定类型。
  2. 迭代器使得更容易指定 for each 循环如何迭代集合的内容。
    // Iterator Example
    public class NumChar
    {
    string[] saNum = { 
      "One", "Two", "Three", 
      "Four", "Five", "Six", 
      "Seven", "Eight", "Nine", 
      "Zero"};
    public 
     System.Collections.IEnumerator 
     GetEnumerator()
    {
    foreach (string num in saNum)
    yield return num;
    }
    }
    // Create an instance of 
    // the collection class
    NumChar oNumChar = new NumChar();
    // Iterate through it with foreach
    foreach (string num in oNumChar)
    Console.WriteLine(num);
    
  3. Partial 类型定义允许将单个类型(如类)拆分为多个文件。Visual Studio 设计器使用此功能将其生成的代码与用户代码分开。
  4. Nullable 类型允许变量包含一个未定义的值。
  5. Anonymous Method 现在可以创建一个代码块作为参数传递。在任何需要委托的地方,都可以使用代码块代替:无需定义新方法。
    button1.Click += 
     delegate { MessageBox.Show( 
     "Click!") };
  6. 命名空间别名限定符(`::`)提供了对访问命名空间成员的更多控制。全局 `::` 别名允许访问可能被代码中的实体隐藏的根命名空间。
  7. Static是一种安全便捷的声明不带实例的静态方法类的途径。在 C# v1.2 中,您会定义类构造函数为私有的以防止类被实例化。
  8. 8. 有八个新的编译器选项:
    1. `/langversion` 选项:可用于指定与特定语言版本兼容。
    2. `/platform` 选项:允许您定位 IPF(IA64 或 Itanium)和 AMD64 体系结构。
    3. `#pragma` warning:用于在代码中禁用和启用单个警告。
    4. `/linkresource` 选项:包含其他选项。
    5. `/errorreport` 选项:可用于通过 Internet 将内部编译器错误报告给 Microsoft。
    6. `/keycontainer` 和 `/keyfile`:支持指定加密密钥。

结论

我认为本文将帮助您理解两种语言的特性,并且您可以根据自己的喜好选择一种语言。如果将来有任何变化,我将更新本文。

历史

  • 2005年4月14日 - 添加主题 - “2005年版本中两种语言的新特性”
  • 2005年3月30日 - 初始版本。
© . All rights reserved.