|
Introduction
Because of the past differences between Microsoft® Visual
Basic™, Microsoft® Visual C™, and Microsoft® Visual C++™, many developers have the
impression that Microsoft® Visual C# .NET™ is a more powerful language than Microsoft®
Visual Basic .NET™. Some developers assume that many things that are possible in
Visual C# .NET are impossible in Visual Basic .NET, just as many things that are
possible in Microsoft® Visual C™ 6.0 and earlier or Microsoft® Visual C++™ 6.0 and
earlier are impossible in Microsoft® Visual Basic™ 6.0 and earlier. This
assumption is incorrect. Although differences exist between Visual Basic .NET
and Visual C# .NET, they are both first-class programming languages that are based
on the Microsoft® .NET Framework, and they are equally powerful. Visual Basic .NET
is a true object-oriented programming language that includes new and improved
features such as inheritance, polymorphism, interfaces, and overloading. Both Visual
Basic .NET and Visual C# .NET use the common language runtime in the .NET
Framework, and almost no performance issues now exist between them. Visual
Basic .NET may be oriented more toward ease of use by providing features such
as late binding, and Visual C# .NET may have a few more “power” features, such
as handling unmanaged code, but the differences are very small compared to what
they were in the past.
This document discusses differences between Visual Basic .NET
and Visual C# .NET. However, the key point to keep in mind is that .NET is
intended to be language-independent. The choice between Visual Basic .NET and Visual
C# .NET is typically based on your personal preference and past experience; for
example, it is easier for Visual Basic 6.0 developers to use Visual Basic .NET,
and for Visual C++ and Java programmers to use Visual C# .NET. The existing
experience of a programmer far outweighs the small differences between the two
languages.
differences between visual basic .net and Visual c# .net
Syntactically, Visual Basic .NET and Visual C# .NET are two
different languages, just as Visual Basic, Visual C, and Visual C++ are
different languages. Visual C# .NET looks more familiar to Visual C, Visual
C++, and Java programmers, and Visual Basic .NET looks more familiar to Visual
Basic developers. The biggest differences between the languages fall into the
following categories:
·
Case sensitivity
·
Variable declaration and assignment
·
Data types
·
Statement termination
·
Statement blocks
·
Use of () vs. []
·
Operators
·
Conditional statements
·
Error handling
·
Overflow checking
·
Parameter passing
·
Late binding
·
Handling unmanaged code
·
Keywords
Case Sensitivity
Identifier names in Visual Basic .NET are not case-sensitive,
but identifier names in Visual C# .NET are. This primarily presents a problem
when you write code, and is not an issue in debugging a program that already
compiles.
Variable Declaration and Assignment
Variables in Visual Basic .NET are declared with the variable
before the data type. In Visual C# .NET, the data type precedes the variables.
Visual Basic .NET
|
Visual C# .NET
|
Dim i, j As Integer
|
int i, j;
|
Dim i As Integer = 7
|
int i = 7;
|
Dim i(6) As Integer
or
Dim i() As Integer = New Integer(6) {}
|
int[] i = new int[6];
|
Dim con As SqlConnection
|
SqlConnection con;
|
Dim x As New Y("ABC")
or
Dim x As Y = New Y("ABC")
|
Y x = new Y("ABC");
|
Data Types
Simple data types have different names in Visual Basic .NET
and Visual C# .NET. For example, Integer
in Visual Basic .NET is int in Visual
C# .NET. However, System.Int32, the
.NET Framework base type for which Integer
and int are aliases, can be used in
both languages. Visual C# .NET also supports the signed byte, unsigned short,
unsigned int, and unsigned long data types, which are not
available in Visual Basic .NET.
The following table lists the different data type names in
each language and the base types for which they are aliases.
Visual Basic .NET
|
Visual C# .NET
|
.NET Framework
|
Boolean
|
bool
|
System.Boolean
|
Byte
|
byte
|
System.Byte
|
Short
|
short
|
System.Int16
|
Integer
|
int
|
System.Int32
|
Long
|
long
|
System.Int64
|
Single
|
float
|
System.Single
|
Double
|
double
|
System.Double
|
Decimal
|
decimal
|
System.Decimal
|
Date
|
System.DateTime
|
System.DateTime
|
String
|
string
|
System.String
|
Char
|
char
|
System.Char
|
Object
|
object
|
System.Object
|
n/a
|
sbyte
|
System.Sbyte
|
n/a
|
ushort
|
System.UInt16
|
n/a
|
uint
|
System.UInt32
|
n/a
|
ulong
|
System.UInt64
|
Statement Termination
Statements in Visual Basic .NET are terminated by the end of
the line. You can use the colon (:) to put multiple statements in a line, and
you can use the line continuation (_) character to make a statement span
several lines.
Statements in Visual C# .NET are terminated by the semicolon
(;). You can use multiple statements per line, and statements can span multiple
lines.
Visual Basic .NET
|
Visual C# .NET
|
A = 5
B = 7 : C = 8
MySub (Arg1, _
Arg2, _
Arg3)
|
A = 5;
B = 7; C = 8;
MySub (Arg1,
Arg2,
Arg3);
|
Statement Blocks
Visual Basic .NET does not use arbitrary statement blocks. Instead,
certain keywords that have a specialized terminating statement are
used instead of the statement blocks.
In Visual C# .NET, braces ({}) are used to delimit a
statement block; otherwise, a single statement is assumed.
Visual Basic .NET
|
Visual C# .NET
|
If A = 5 Then
DoSomething()
DoSomethingAgain()
End If
|
If (a == 5)
{
DoSomething();
DoSomethingAgain();
}
or
if (a == 5)
DoSomething();
DoSomethingAgain(); //This is not part of
//the
if statement.
|
Use of () vs. [ ]
Visual Basic .NET uses parentheses () to delimit array
elements, function arguments, and property indexes.
Visual C# .NET uses parentheses () to delimit function
arguments, and brackets ([]) to delimit array elements and property indexes.
Purpose
|
Visual Basic .NET
|
Visual C# .NET
|
Declare an array
|
Dim a() As Long
Dim a(3, 5) as Integer
|
int[] x = new int[5];
|
Initialize an array
|
Dim a() As Long = {3, 4, 5}
|
int[] x = new int[5] {1, 2, 3, 4, 5};
|
Reallocate array
|
Redim
|
n/a
|
Functions Arguments
|
X= A(5)
MySub (A, B, C)
|
MySub(A, B, C);
|
Property Indexes
|
Y = MyDataSet.Tables_
("Author").Rows(5)._
Columns("AuthorID")
|
Y = MyDataSet.Tables["Author"].Rows[5].Columns["AuthorID"]
|
Operators
The operators that are used in Visual Basic .NET and Visual
C# .NET are quite different. The following table lists the main operators. This
information can also be found in the Microsoft® Visual Studio .NET™ documentation.
Operator
|
Visual Basic .NET
|
Visual C# .NET
|
||||
Additive
|
|
|
||||
Addition
|
+
|
+
|
||||
Subtraction
|
-
|
-
|
||||
Multiplicative
|
|
|
||||
Multiplication
|
*
|
*
|
||||
Division
|
/
|
/
|
||||
Integer division
|
\
|
/ (depending on the operands)
|
||||
Modulus (division returning only the remainder)
|
Mod
|
%
|
||||
Exponentiation
|
^
|
n/a
|
||||
Assignment
|
|
|
||||
Assignment
|
=
+= -= *=
/*
|
=
+= -= *=
/*
|
||||
Integer division
|
\=
|
/= (depending on the operands)
|
||||
Concatenate
|
&=
|
+=
|
||||
Modulus
|
n/a
|
%=
|
||||
Left shift
|
n/a
|
<<=
|
||||
Right shift
|
n/a
|
>>=
|
||||
Bitwise AND
|
n/a
|
&=
|
||||
XOR
|
n/a
|
^=
|
||||
OR
|
n/a
|
|=
|
||||
Relational and equality
|
|
|
||||
Less than
|
<
|
<
|
||||
Less than or equal to
|
<=
|
<=
|
||||
Greater than
|
>
|
>
|
||||
Greater than or equal to
|
>=
|
>=
|
||||
Equal
|
=
|
==
|
||||
Not equal
|
<>
|
!=
|
||||
Compare two object reference variables
|
Is
|
==
|
||||
Compare object reference type
|
TypeOf x Is Class1
|
x is Class1
|
||||
Compare strings
|
=
|
== or String.Equals()
|
||||
Concatenate strings
|
&
|
+
|
||||
Shortcircuited Boolean AND
|
AndAlso
|
&&
|
||||
Shortcircuited Boolean OR
|
OrElse
|
||
|
||||
Shift
|
|
|
||||
Left shift
|
n/a
|
<<
|
||||
Right shift
|
n/a
|
>>
|
||||
Scope resolution
|
|
|
||||
Scope resolution
|
.
|
., base
|
||||
Postfix
|
|
|
||||
Type cast
|
Cint, CDbl, …, CType
|
(type)
|
||||
Member selection
|
.
|
.
|
||||
Postfix increment
|
n/a
|
++
|
||||
Postfix decrement
|
n/a
|
--
|
||||
Unary
|
|
|
||||
Indirection
|
n/a
|
* (unsafe mode only)
|
||||
Address of
|
AddressOf
|
& (unsafe mode only)
|
||||
Logical NOT
|
Not
|
!
|
||||
One's complement
|
Not
|
~
|
||||
Prefix increment
|
n/a
|
++
|
||||
Prefix decrement
|
n/a
|
--
|
||||
Size of type
|
n/a
|
sizeof
|
||||
Bitwise
|
|
|
||||
Bitwise NOT
|
Not
|
~
|
||||
Bitwise AND
|
And
|
&
|
||||
Bitwise XOR
|
Xor
|
^
|
||||
Bitwise OR
|
Or
|
|
|
||||
Logical
|
|
|
||||
Logical AND, OR
|
And
|
&&
|
||||
Logical OR
|
Or
|
||
|
||||
Conditional
|
|
|
||||
Conditional
|
IIf
|
?:
|
||||
Pointer to member
|
|
|
||||
Pointer to member
|
n/a
|
. (Unsafe mode only)
|
||||
Conditional Statements
The following table lists the differences in the conditional
statements that Visual Basic .NET and Visual C# .NET use.
Conditional Statement
|
Visual Basic .NET
|
Visual C# .NET
|
Decision structure (selection)
|
Select Case …, Case, Case Else, End Select
|
switch, case, default,
|
Decision structure (if … then)
|
If … Then, ElseIf … Then, Else, End If
|
if, else
|
Loop structure (conditional)
|
While… End While, Do [While, Until] …, Loop [While, Until]
|
do, while, continue
|
Loop structure (iteration)
|
For …, [Exit For,] Next
For Each …, [Exit For,] Next
|
for, foreach
|
Control flow statement
|
Exit, GoTo, Stop, End, Return,
|
break, continue, goto, return,
throw
|
Error Handling
Unstructured error handling is for backward compatibility. Visual
Basic .NET supports both structured and unstructured error handling, but Visual
C# .NET supports only structured error handling.
Purpose
|
Visual Basic .NET
|
Visual C# .NET
|
Structured error handling
|
Try
…
Catch …
Finally
… End Try |
try, catch, finally,
throw |
Unstructured error handling
|
On Error GoTo …
On Error Resume Next
|
n/a
|
Overflow Checking
Visual Basic .NET has a project level setting to check for
overflow. However, the checking can only be turned on and off at the project
level, instead of at the level of an expression or a block of code. To turn overflow
checking on and off, follow these steps:
1.
On the Project
menu, click Properties.
2.
Under Configuration
Properties, select Optimizations,
and then select or clear Remove integer
overflow checks.
Visual C# .NET statements can run in either a checked or an unchecked
context. In a checked context, arithmetic overflow raises an exception error.
In an unchecked context, arithmetic overflow is ignored and the result is
truncated. This can be used on an expression or a block of code.
Parameter Passing
Visual Basic .NET uses ByVal
for passing parameters by value, and uses ByRef
for passing parameters by reference. Visual Basic .NET can also force parameters
to be passed by value, regardless of how they are declared, by enclosing the
parameters in extra parentheses. Visual Basic .NET also supports optional
parameters, which are not available in Visual C# .NET.
Visual C# .NET does not have a way to pass reference types
(objects) strictly by value. You can either pass the reference (basically a
pointer) or a reference to the reference (a pointer to a pointer). Unmanaged Visual
C# .NET methods can take pointers just like Visual C++ methods. To pass a parameter
by reference, Visual C# .NET uses the ref
keyword. To use a ref parameter, the argument must explicitly be passed
to the method as a ref argument. The value of a ref argument is
passed to the ref parameter.
Purpose
|
Visual Basic .NET
|
Visual C# .NET
|
Pass by value
|
Public Sub ABC (ByVal y As Long)
…
End Sub
ABC(x)
ABC((x))
|
void ABC(int x)
{
...
}
ABC(i);
|
Pass by reference
|
Public Sub ABC(ByRef y As Long)
…
End Sub
ABC(x)
|
void ABC(ref int x)
{
...
}
ABC(ref i);
|
Optional parameter
|
Supported
|
n/a
|
Late Binding
Both Visual Basic .NET and Visual C# .NET can implement
implicit late binding through reflection. However, implementing late binding in
Visual Basic .NET is much easier than in Visual C# .NET.
In Visual Basic .NET, as in Visual Basic 6.0, the Visual
Basic compiler calls a helper method behind the scenes that uses reflection to
obtain the object type. The arguments that are passed to the helper method
cause the appropriate method to be invoked at run time. These arguments are the
object on which to invoke the method, the name of the invoked method that is a
string, and the arguments that are passed to the invoked method that is an
array of objects. Additionally, you can implement late binding explicitly in
code through reflection.
Imports System
Module Hello
Sub Main()
' Set up
variable.
Dim helloObj As
Object
' Create the
object.
helloObj = new
HelloWorld()
' Invoke the
print method as if it was early bound
' even though it
is really late bound.
helloObj.PrintHello("Visual Basic Late Bound")
End Sub
End Module
In Visual C# .NET, implementing late binding is more difficult
than in Visual Basic .NET. Instead of having the compiler implement late
binding, you must explicitly implement late binding in code by using reflection.
Handing Unmanaged Code
Visual C# .NET permits you to write unmanaged code. In unmanaged
code, you can do things such as declare and operate on pointers, perform
conversions between pointers and integral types, and take the address of
variables. In a sense, writing unmanaged code is much like writing Visual C
code in a Visual C# .NET program.
Because code that is written by using an unmanaged context
cannot be verified to be safe, it is run only when the code is fully trusted. Do
not use unmanaged context to try to write Visual C code in Visual C# .NET. Unmanaged
code must be clearly marked with the modifier unsafe so that developers cannot use unmanaged features
accidentally, and the execution engine works to make sure that unmanaged code
cannot be run in a non-trusted environment. The scope of the unmanaged context
extends from the parameter list to the end of the function, so pointers can also
be used in the parameter list.
In Visual Basic .NET, you cannot write unmanaged code.
Keywords
The following table lists the keywords that Visual Basic .NET
and Visual C# .NET use in several categories. This information can also be
found in the Visual Studio .NET online documentation.
Purpose
|
Visual Basic .NET
|
Visual C# .NET
|
||||
Object Oriented Programming
|
|
|
||||
Indicates a class constructor
|
Public Class Class1
Public Sub New(..)
MyBase.New
…
End Sub
…
End Class
Note: You have to call the base class constructor
explicitly in Visual Basic .NET.
|
public class Class1
{
public
Class1(..)
{
…
}
….
}
Note: The call to the base class
constructor (base()) is generated automatically by the compiler in Visual C#
.NET if you do not include constructor initializers.
|
||||
Indicates a class destructor
Note: The Destructor
or Finalize method is called by
garbage collection.
|
Protected Overrides Sub Finalize()
m_Gadget = Nothing
m_Gear = Nothing
MyBase.Finalize()
End Sub
|
public class Class1
{
public
~Class1()
{
….
}
}
|
||||
Declares a class
|
Class
|
class
|
||||
Indicates class inheritance
|
Public Class A
Inherits B
…
End Class
|
public class A : B
{
…
}
|
||||
Indicates that the class can only be inherited and cannot be
instantiated
|
MustInherit
|
abstract
|
||||
Indicates that the class cannot be inherited
|
NotInheritable
|
sealed
|
||||
Calls your own implementation of the method instead of an
overridden method in the derived class
|
MyClass
|
None
|
||||
Refers to a base class from the derived class
|
MyBase
|
base
|
||||
Declares a type-safe reference to a class method
|
Delegate
|
delegate
|
||||
Indicates that the method or the property overrides the
implementation in its base class
|
Overrides
|
override
|
||||
Indicates that these methods have no implementation and must be
implemented in derived classes
|
MustOverride
(in MustInherit
class)
|
abstract
(in abstract
class)
|
||||
Indicates that the method or the property cannot be overridden
in derived classes
|
NotOverridable
Note: By default, methods are not overridable.
|
sealed
|
||||
Indicates that the method or the property can be overridden in
an inheriting class
|
Overridable
|
virtual
|
||||
Overloads a procedure, a function, or a method
|
Overloads
|
None. Define functions with same name but different signatures.
|
||||
Specifies that a variable can contain an object whose events
you want to handle
|
WithEvents
|
No specific keyword
|
||||
Specifies the events for which an event procedure will be
called
|
Handles
(Event procedures can still be
associated with a WithEvents variable by naming pattern.)
|
n/a
|
||||
Evaluates an object expression one time to access multiple
members
|
With objExpr
<.member>
<.member>
End With
|
n/a
|
||||
Refers to the current object
|
Me
|
This
|
||||
Declares an enumerated type
|
Enum
…
End Enum
|
Enum
|
||||
Declares an interface
|
Interface
|
interface
|
||||
Implements an interface
|
Implements
|
class C1
: I1
|
||||
Indicates an indexer
|
Default Property
|
public string this[int index]
{
get {return
List[index];}
set
{List[index]=value;}
}
|
||||
Class Access Modifiers
|
|
|
||||
Indicates that the modifier is accessible outside the project
or the assembly
|
Public
|
public
|
||||
Indicates that the modifier is accessible inside the assembly
only
|
Friend
|
internal
|
||||
Indicates that the modifier is accessible only in the project
(for nested classes, in the enclosing class)
|
Private
|
private
|
||||
Class Member Access Modifiers
|
|
|
||||
Indicates that the modifier is accessible outside the class and
the project
|
Public
|
public
|
||||
Indicates that the modifier is accessible outside the class,
but in the project
|
Friend
|
internal
|
||||
Indicates that the modifier is only accessible in a class or a module
|
Private
|
private
|
||||
Indicates that the modifier is accessible only to current and
derived classes
|
Protected
|
protected
|
||||
Indicates the union of Protected and Friend or Internal
|
Protected Friend
|
protected internal
|
||||
Indicates that the members are shared across all instances
|
Shared
|
static
|
||||
Miscellaneous Lifetime
|
|
|
||||
Preserves the local variables for the procedure
|
Static
|
n/a
|
||||
Other
|
|
|
||||
Calls the Windows API
|
Declare statement
|
use Platform Invoke
|
||||
Indicates a comment
|
‘, Rem
|
//, /* */ for miltine comments,
|
||||
Indicates a constant
|
Const
|
Const, readonly
|
||||
Creates a new object
|
New, CreateObject
|
new
|
||||
Declares a function or a method with no return value
|
Sub
|
void
|
||||
Declares that an object can be modified asynchronously
|
n/a
|
volatile
|
||||
Declares a variable
|
Private, Public, Friend, Protected, Static, Shared, Dim
|
declarators (keywords include user-defined types and
built-in types)
|
||||
Declares a variable explicitly
|
Option Explicit
|
None (All variables must be declared before use)
|
||||
Declares and raises an event
|
Event, RaiseEvent
|
event
|
||||
Declares a structure
|
Structure
…
End Structure
|
struct
|
||||
Defines a default property
|
Default
|
by using indexers
|
||||
Declares a null object
|
Nothing
|
null
|
||||
Declares a namespace
|
Namespace
…
End Namespace
|
Namespace
{
…
}
|
||||
Indicates namespace usage
|
Imports
|
using
|
||||
Retrieves a character from a string
|
GetChar Function
|
[ ]
|
||||
Returns the address of a function
|
AddressOf (For class members, this operator returns a reference
to a function in the form of a delegate instance)
|
delegate
|
||||
Tests for a null object
|
Obj Is Nothing
|
obj == null
|
||||
Tests for a database null expression
|
IsDbNull
|
n/a
|
||||
Threads primitives
|
SyncLock
|
lock
|
||||
Conclusion
Based on your personal preference and past experience, you can
use either Visual Basic .NET or Visual C# .NET to build solutions. Although
differences do exist between the two languages, both languages use the .NET
Framework common language runtime and are equally powerful. This document only
briefly discusses the differences in syntax between Visual Basic .NET and
Visual C# .NET. For more detailed information about these differences and other
differences that exist between the two programming languages, see the Visual
Studio .NET online help.