VB.NET 和 C# 完全对比






4.87/5 (178投票s)
2005年3月30日
11分钟阅读

1610580
本文解释了 VB.NET 和 C# 的优点、区别和新特性。
目录
- 引言
- 两种语言的优点
- 关键字区别
- 数据类型区别
- 运算符区别
- 编程区别
- 2005年版本中两种语言的新特性
- 结论
- 历史
引言
有些人喜欢 VB.NET 的自然语言、不区分大小写的方法,而另一些人则喜欢 C# 的简洁语法。但两者都可以访问相同的框架库。我们将在以下主题中讨论这些区别:
- 两种语言的优点
- 关键字区别
- 数据类型区别
- 运算符区别
- 编程区别
两种语言的优点
| VB.NET | C# | 
| 
 | 
 | 
关键字区别
| 目的 | VB.NET | C# | 
| 声明变量 | 
 | 
 | 
| 声明命名常量 | 
 | 
 | 
| 创建新对象 | 
 | 
 | 
| 函数/方法不返回值 | 
 | 
 | 
| 重载函数或方法(Visual Basic:重载过程或方法) | 
 | (此目的无需语言关键字) | 
| 引用当前对象 | 
 | 
 | 
| 对当前对象的虚拟方法进行非虚拟调用 | 
 | 不适用 | 
| 从字符串中检索字符 | 
 | 
 | 
| 声明复合数据类型(Visual Basic:Structure) | 
 | 
 | 
| 初始化对象(构造函数) | 
 | 构造函数,或系统默认类型构造函数 | 
| 直接终止对象 | 不适用 | 不适用 | 
| 垃圾回收回收对象前系统调用的方法7 | 
 | 析构函数 | 
| 在声明处初始化变量 | Dim x As Long = 5Dim c As New _
   Car(FuelTypeEnum.Gas) | // initialize to a value:
int x = 123;
// or use default 
// constructor:
int x = new int(); | 
| 获取函数地址 | 
 | 
 | 
| 声明对象可以异步修改 | 
 | 
 | 
| 强制显式声明变量 | 
 | n/a. (所有变量必须在使用前声明) | 
| 测试不指向对象的对象变量 | 
 | 
 | 
| 不指向对象的对象变量的值 | 
 | 
 | 
| 测试数据库 null 表达式 | 
 | 不适用 | 
| 测试 Variant 变量是否已初始化 | 不适用 | 不适用 | 
| 定义默认属性 | 
 | 通过使用索引器 | 
| 引用基类 | 
 | 
 | 
| 声明接口 | 
 | 
 | 
| 指定要实现的接口 | 
 | 
 | 
| 声明类 | 
 | 
 | 
| 指定类只能继承。无法创建类的实例。 | 
 | 
 | 
| 指定类不能被继承 | 
 | 
 | 
| 声明枚举类型 | 
 | 
 | 
| 声明类常量 | 
 | 
 | 
| 从基类派生类 | 
 | 
 | 
| 重写方法 | 
 | 
 | 
| 声明必须在派生类中实现的函数 | 
 | 
 | 
| 声明不能被重写的方法 | 
 | 
 | 
| 声明虚拟方法、属性(Visual Basic)或属性访问器(C#、C++) | 
 | 
 | 
| 在派生类中隐藏基类成员 | 
 | 不适用 | 
| 声明对类方法的类型安全引用 | 
 | 
 | 
| 指定一个变量可以包含一个你想处理其事件的对象 | 
 | (编写代码 - 无特定关键字) | 
| 指定将调用事件过程的事件 | 
 | 不适用 | 
| 评估一次对象表达式,以便访问多个成员 | With objExpr 
  <.member>
  <.member> 
End With | 不适用 | 
| 结构化异常处理 | Try <attempt>
Catch
<handle errors>
Finally
<always execute>
End Try | 
 | 
| 决策结构(选择) | 
 | 
 | 
| 决策结构(if ... then) | 
 | 
 | 
| 循环结构(条件) | 
 | 
 | 
| 循环结构(迭代) | 
 | 
 | 
| 声明数组 | 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}; | 
| 重新分配数组 | 
 | 不适用 | 
| 项目或程序集外可见 | 
 | 
 | 
| 程序集外不可见(C#/Visual Basic)或包内不可见(Visual J#、JScript) | 
 | 
 | 
| 仅在项目内可见(对于嵌套类,在包含类内) | 
 | 
 | 
| 类和项目或模块外部可访问 | 
 | 
 | 
| 类外部、项目内部可访问 | 
 | 
 | 
| 仅类或模块内部可访问 | 
 | 
 | 
| 仅当前类和派生类可访问 | 
 | 
 | 
| 保留过程的局部变量 | 
 | 不适用 | 
| 由类的所有实例共享 | 
 | 
 | 
| 注释代码 | 
 | 
 | 
| 区分大小写? | 否 | 是 | 
| 调用 Windows API | 
 | 使用 Platform Invoke | 
| 声明和引发事件 | 
 | 
 | 
| 线程原语 | 
 | 
 | 
| 跳转到 | 
 | 
 | 
数据类型区别
| 目的/大小 | VB.NET | C# | 
| 十进制 | 
 | 
 | 
| 日期 | 
 | 
 | 
| (变化) | 
 | 
 | 
| 1 字节 | 
 | 
 | 
| 2 字节 | 
 | 
 | 
| 2 字节 | 
 | 
 | 
| 4 字节 | 
 | 
 | 
| 8 字节 | 
 | 
 | 
| 4 字节 | 
 | 
 | 
| 8 字节 | 
 | 
 | 
运算符区别
| 目的 | VB.NET | C# | 
| 整数除法 | 
 | 
 | 
| 模运算(仅返回余数的除法) | 
 | 
 | 
| 求幂 | 
 | 不适用 | 
| 整数除法赋值 | 
 | 
 | 
| 字符串连接 | 
 | 
 | 
| 模运算 | 不适用 | 
 | 
| 按位与 | 不适用 | 
 | 
| 按位异或 | 不适用 | 
 | 
| 按位或 | 不适用 | 
 | 
| 等于 | 
 | 
 | 
| 不等于 | 
 | 
 | 
| 比较两个对象引用变量 | 
 | 
 | 
| 比较对象引用类型 | 
 | 
 | 
| 连接字符串 | 
 | 
 | 
| 短路布尔与 | 
 | 
 | 
| 短路布尔或 | 
 | 
 | 
| 作用域解析 | 
 | 
 | 
| 数组元素 | 
 | 
 | 
| 类型转换 | 
 | 
 | 
| 后缀增量 | 不适用 | 
 | 
| 后缀减量 | 不适用 | 
 | 
| 间接寻址 | 不适用 | 
 | 
| 取址 | 
 | 
 | 
| 逻辑非 | 
 | 
 | 
| 按位非(一的补码) | 
 | 
 | 
| 前缀增量 | 不适用 | 
 | 
| 前缀减量 | 不适用 | 
 | 
| 类型大小 | 不适用 | 
 | 
| 按位与 | 
 | 
 | 
| 按位异或 | 
 | 
 | 
| 按位或 | 
 | 
 | 
| 逻辑与 | 
 | 
 | 
| 逻辑或 | 
 | 
 | 
| Conditional | 
 | 
 | 
| 成员指针 | 不适用 | 
 | 
编程区别
| 目的 | 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 开发人员,您现在可以使用显式的多线程来创建多线程、可扩展的应用程序。该语言具有以下新特性: 
 | 随着 Visual Studio 2005 的发布,C# 语言已更新到 2.0 版本。该语言具有以下新特性: 
 | 
结论
我认为本文将帮助您理解两种语言的特性,并且您可以根据自己的喜好选择一种语言。如果将来有任何变化,我将更新本文。
历史
- 2005年4月14日 - 添加主题 - “2005年版本中两种语言的新特性”
- 2005年3月30日 - 初始版本。
