C# – Visual Basic Bilingual Dictionary (2015)

Chapter 1

C# to Visual Basic

The C# entries in this chapter appear alphabetically by keyword or feature. Locate a language entry to see its Visual Basic equivalent. Entries identified by symbols appear before those starting with letters, and in the following order.

!   #   $   %   &   (   *   +   , -   .   /   :   ;   <   =   >   ?   @   [   \   ^ {   |   ~

! Negation Operator

The Visual Basic equivalent of C#’s ! Boolean-centric operator is the Not operator.

C#

bool opposite = !originalValue;

VISUAL BASIC

Dim opposite As Boolean = Not originalValue

The Not operator is also a bitwise complement operator when used with integer operands. The equivalent in C# for that variation is the ~ operator.

See Also

~ Bitwise Complement Operator

!= Comparison Operator

When comparing value types, Visual Basic’s <> inequality operator is identical to C#’s != operator, and appears in the same binary-operator position.

C#

if (teamPlayers != 9)

VISUAL BASIC

If (teamPlayers <> 9) Then

For string comparisons, the <> operator once again replicates C#’s != operator. However, VB’s Option Compare statement impacts the way that strings compare to each other. By default, both C# and Visual Basic perform binary-level comparisons of strings. However, if a VB project or source file employs Option Compare Text , the comparison instead uses culture-specific text sorting rules.

For reference types other than strings, C#’s != operator tests whether the two references being compared refer to the same underlying instance. This syntax is invalid in Visual Basic (at least when Option Strict On is used). Instead, VB programs should use the IsNotoperator with a second instance, or with Nothing.

C#

// ----- Standard instance comparison.

if (firstIntance != secondInstance)

// ----- Comparisons with null.

if (anotherInstance != null)

VISUAL BASIC

' ----- Standard instance comparison.

If (firstInstance IsNot secondInstance) Then

' ----- Comparisons with null (Nothing in VB).

If (anotherInstance IsNot Nothing) Then

#define Directive

In C#, the #define directive declares preprocessing constants. These constants are in essence Boolean, in that they either exist (true-like) or they don’t (false-like). The parallel #undef directive removes constants previously declared with #define.

C#

#define TestVersion

In Visual Basic, preprocessing constants come into being using the #Const directive. Unlike the Boolean nature of C# preprocessing constants, the parallel constants in VB can be Boolean, integer, floating point, string, or date values.

VISUAL BASIC

#Const TestVersion = "Beta 0.7"

To clear a previously declared VB constant from use, assign it a value of Nothing.

VISUAL BASIC

#Const TestVersion = Nothing

#error Directive

There is no equivalent in Visual Basic for the #error directive.

#if Directive

The general syntax of preprocessing conditional statements in Visual Basic parallels closely the usage found in C#, with some minor spelling and casing differences.

C# Term

Visual Basic Term

#if

#If...Then

#elif

#ElseIf...Then

#else

#Else

#endif

#End If

The key difference appears in the conditions themselves. Preprocessor values in C# act like Booleans; they either exist or they don’t. In Visual Basic, preprocessor values exist as Booleans, integers, floating-point values, strings, or dates, and you can apply typical VB operators to those values.

C#

#if TestVersion

    // ----- Test-specific code here.

#elif (OldVersion == false)

    // ----- Backward-compatible code here.

#else

    // ----- Standard code here.

#endif

VISUAL BASIC

#If TestVersion Then

    ' ----- Test-specific code here.

#ElseIf (OldVersion = False) Or

        (TargetVersion < 2.5) Then

    ' ----- Backward-compatible code here.

#Else

    ' ----- Standard code here.

#End If

C# allows the ==, !=, &&, ||, and ! operators, the true and false constants, and parentheses within the conditional expressions. Visual Basic expressions can include any of the standard VB comparison operators (=, <>, <, >, <=, >=); mathematical, string, and logical operators (+ , -, *, /, \, ^, Mod, <<, >>, &, Not , And, Or, Xor, AndAlso, OrElse); intrinsic casting and conversion functions (DirectCast, TryCast, CType, CBool , CByte, CChar, CDate , CDec, CDbl, CInt, CLng, CObj, CSByte, CShort, CSng, CStr, CUInt, CULng, andCUShort); the If function; and parentheses, as long as the final result is Boolean. String values in these expressions use binary-level comparisons instead of culture-specific text comparisons.

#line Directive

There is no equivalent in Visual Basic for the #line directive.

#pragma Directive

In generated Visual Studio source files, C#’s #pragma checksum directive serves the same purpose as Visual Basic’s #ExternalChecksum directive. Neither statement should be used directly within code, except as generated by the .NET Framework.

New with Visual Studio 2015

Older editions of Visual Basic lacked an equivalent for C#’s #pragma warning statement, but it was added to VB in its 2015 release. Except for the keywords included in the statements, the usage is nearly identical between the languages.

C#

// ----- Turn an error off.

#pragma warning disable CS1234

// ----- Turn it back on later.

#pragma warning restore CS1234

VISUAL BASIC

' ----- Turn an error off.

#Disable Warning BC1234

' ----- Turn it back on later.

#Enable Warning BC1234

Both languages accept comma-delimited lists of error codes. For reasons of backward compatibility, C# allows purely numeric error codes. In newer code, these numbers include a CS prefix. VB does not permit number-only codes.

#region Directive

Visual Basic’s #Region directive is equivalent to C#’s #region directive. The descriptive tag that follows the directive keyword is enclosed in double-quotes in VB, but such quotes are not used in C#.

C#

#region Utility Functions

    // ----- Collapsable code here.

#endregion

VISUAL BASIC

#Region "Utility Functions"

    ' ----- Collapsable code here.

#End Region

Both languages allow nesting of these regions. In C#, additional text (such as the name included with the initial #region directive) may appear after the #endregion directive. In Visual Basic, such text can only appear as a trailing comment.

C#

#endregion Utility Functions

VISUAL BASIC

#End Region  ' Utility Functions

New with Visual Studio 2015

In C#, regions can appear within method bodies, and a region can even begin in one method and end in a later method. Neither of these options was valid in older editions of Visual Basic, but they were both added to the language starting with its 2015 release.

#undef Directive

To clear a previously declared preprocessor constant in Visual Basic, assign it a value of Nothing.

C#

#undef TestVersion

VISUAL BASIC

#Const TestVersion = Nothing

#warning Directive

There is no equivalent in Visual Basic for the C# #warning directive.

$ Interpolated String Indicator

New with Visual Studio 2015

In 2015, both C# and Visual Basic added string interpolation, a method of generating formatted strings using string literals. Both languages share an identical syntax for such strings, prefixing them with a $ symbol, and using curly braces to contain the interpolated sections.

C#

message = $"Meet {name} on {meetDate:dddd}";

VISUAL BASIC

message = $"Meet {name} on {meetDate:dddd}"

% Modulo Operator

Visual Basic includes a Mod operator that is identical to C#’s % modulo operator.

C#

int penniesNeeded = totalInCents % 5;

VISUAL BASIC

Dim penniesNeeded As Integer = totalInCents Mod 5

%= Assignment Operator

Visual Basic does not include an equivalent for C#’s %= operator. You must perform the modulo (Mod) and assignment operations separately in VB.

C#

leftOver %= 10;

VISUAL BASIC

leftOver = leftOver Mod 10

See Also

Assignment Operators

& Address Operator

Visual Basic does not include direct support for pointer operations, and therefore does not include an operator that establishes a fixed address for an object.

See Also

Pointers

& Conjunction Operator

In general, Visual Basic’s And operator is identical to C#’s & operator, both for integer (bitwise) and Boolean (logical) operations.

C#

bool clapHands = (happy & knowIt);

VISUAL BASIC

Dim clapHands As Boolean = (happy And knowIt)

When applying Option Strict Off to a Visual Basic project or source file, using the And operator with one integer operand and one Boolean operand forces the Boolean value to an integer (0 or ‑1), and then performs a bitwise operation. C# does not allow this mixture of operand types.

Visual Basic does include its own & operator. However, it is used for string concatenation; it does not process logical or bitwise operations.

&& Conjunction Operator

Visual Basic’s AndAlso operator is identical to C#’s && short-circuiting conjunction operator.

C#

if ((result != null) && (result.Length > 10))

VISUAL BASIC

If ((result IsNot Nothing) AndAlso

    (result.Length > 10)) Then

&= Assignment Operator

Visual Basic does not include an equivalent for C#’s &= operator. You must perform the conjunction (And) and assignment operations separately in VB.

C#

finalSet &= testFlag;

VISUAL BASIC

finalSet = finalSet And testFlag

Visual Basic does include its own &= operator. However, it combines string concatenation and assignment, and does not process logical or bitwise operations.

See Also

Assignment Operators

( ) Cast Expression

See

Conversion and Casting

( ) Expression Grouping

When used to group expressions, parentheses in Visual Basic are identical in syntax to grouping parentheses in C#. However, there are times when a set of parentheses is required around an expression in C#, but is optional when creating the equivalent statement in VB. For instance, the condition for an if statement in C# must be enclosed in parentheses, but Visual Basic does not have this requirement.

C#

// ----- Parentheses required in C#.

if (totalCount >= 100)

VISUAL BASIC

' ----- Parentheses optional in Visual Basic.

If totalCount >= 100 Then

* Dereference Operator

Visual Basic does not include direct support for pointer operations, and therefore does not include a dereferencing operator.

See Also

-> Member Access Operator, Pointers

* Multiplication Operator

The * multiplication operator in Visual Basic uses the same symbol and syntax as in C#.

C#

result = originalValue * 5;

VISUAL BASIC

result = originalValue * 5

*= Assignment Operator

Visual Basic’s *= assignment operator is identical to the one found in C#, both in syntax and in purpose.

C#

originalValue *= 5;

VISUAL BASIC

originalValue *= 5

See Also

Assignment Operators

+ Addition Operator

C#’s + operator serves as both a numeric addition operator and a string concatenation operator.

C#

int result = number1 + number2;      // Addition

string greeting = "Hello, " + name;  // Concatenation

The + operator in Visual Basic also works for both addition and concatenation.

VISUAL BASIC

Dim result As Integer = number1 + number2  ' Addition

Dim greeting As String =

    "Hello, " + name  ' Concatenation

However, the rules surrounding concatenation in VB differ depending on the data types of the operands and the state of the Option Strict statement in effect. For example, when one operand is numeric and one is string, VB will try to coerce the string to a number (even non-numeric strings) when Option Strict Off is used, and will generate a compile-time error when using Option Strict On. When confronted with a similar situation, C# converts the number to string before concatenating the operands, a variation not used by VB’s + operator. Because of the possibility for ambiguity in such statements, Visual Basic’s & operator is the preferred tool for concatenating strings, leaving the + operator for addition only.

VISUAL BASIC

Dim result As Integer = number1 + number2  ' Addition

Dim greeting As String =

    "Hello, " & name  ' Concatenation

+ Unary-Plus Operator

Both C# and Visual Basic permit a prefix unary-plus operator before numeric literals and expressions. The syntax is identical between the two languages.

++ Increment Operator

Visual Basic does not include an equivalent to C#’s ++ increment operator, in either its prefix or postfix notation. Use the + addition operator or the += assignment operator instead.

C#

// ----- result will be 5, originalValue will be 6.

originalValue = 5;

result = originalValue++;

VISUAL BASIC

' ----- The postfix operation becomes two

'       VB statements.

originalValue = 5

result = originalValue

originalValue += 1

See Also

+ Addition Operator, += Assignment Operator, -- Decrement Operator

+= Assignment Operator

Visual Basic’s += assignment operator is identical to the one found in C#, both in syntax and in purpose.

C#

originalValue += 5;

VISUAL BASIC

originalValue += 5

Although the += operator also performs string concatenation in Visual Basic, the &= assignment operator is a better choice for joining strings in VB.

See Also

Assignment Operators

+= Event Subscription Operator

C# uses the += event subscription operator to attach to an object’s events those event handlers that conform to a specific delegate, or to associate a method with a delegate instance in general.

C#

// ----- button1_Click method defined elsewhere,

//       and conforms to same delegate used by

//       the Click event.

button1.Click += button1_Click;

In Visual Basic, the AddHandler statement performs this same type of event handler attachment. The AddressOf operator appears before the event handler name.

VISUAL BASIC

' ----- Button1_Click method defined elsewhere,

'       and conforms to same delegate used by

'       the Click event.

AddHandler Button1.Click, AddressOf Button1_Click

Visual Basic also has an alternate syntax that uses WithEvents on the object declaration, and replaces AddHandler with the Handles clause on the event handler.

VISUAL BASIC

' ----- Define the instance.

Public WithEvents Button1 As New Button()

' ----- Define the handler.

Sub Button1_Click(ByVal sender As Object,

        ByVal e As EventArgs) Handles Button1.Click

End Sub

Both C# and Visual Basic can attach inline event handlers to an event. See the “delegate Statement” entry in this chapter for an example.

See Also

delegate Statement

, Punctuator

In general, Visual Basic’s use of the comma parallels those uses found in C#, with two notable exceptions. The first exception concerns C#’s use of a comma to separate assignments and conditions in for Statements.

C#

for (counter = 1, mask = "*"; counter <= 10;

     counter++, mask += "*")

Visual Basic’s For Statement is much simpler, restricting control of the loop to a single numeric value, removing the need to support a comma in this context.

VISUAL BASIC

Mask = "*"

For counter = 1 To 10

    mask &= "*"

    ' ----- More code.

Next counter

The second exception deals with optional arguments. In C#, when calling a method with multiple optional arguments, if you only want to supply one of the later optional arguments, you must employ named arguments.

C#

// ----- Assume function Task has three arguments,

//       (a, b, c), where only 'a' is required:

//          void Task(int a, int b = 1, int c = 2)

Task(aValue, c: cValue);

This same syntax works in Visual Basic (using the := symbol for the named argument indicator instead of C#’s : symbol). However, Visual Basic also allows you to pass arguments by position, leaving any optional arguments blank as desired.

VISUAL BASIC

' ----- b will use its default value.

Task(aValue, , cValue)

See Also

Initializers

- Subtraction Operator

The – subtraction operator in Visual Basic uses the same symbol and syntax as in C#.

C#

result = originalValue - 5;

VISUAL BASIC

result = originalValue - 5

- Unary-Minus Operator

The – unary-minus operator in Visual Basic uses the same symbol and syntax as in C#.

C#

negativeVersion = -originalValue;

VISUAL BASIC

negativeVersion = -originalValue

-- Decrement Operator

Visual Basic does not include an equivalent to C#’s -- decrement operator, in either its prefix or postfix notation. Use the – subtraction operator or the -= assignment operator instead.

C#

// ---- result will be 5, originalValue will be 4.

originalValue = 5;

result = originalValue--;

VISUAL BASIC

' ----- The postfix operation becomes two VB statements.

originalValue = 5

result = originalValue

originalValue -= 1

-= Assignment Operator

In its typical use, C#’s -= assignment operator is identical to the one found in Visual Basic, both in syntax and in purpose.

C#

originalValue -= 5;

VISUAL BASIC

originalValue -= 5

See Also

-= Event Unsubscription Operator, Assignment Operators

-= Event Unsubscription Operator

Visual Basic uses the RemoveHandler statement, in conjunction with the AddressOf operator, to detach event handlers from object instances, or to disassociate a method from a delegate instance in general.

C#

Form1.Click -= ClickEventHandler;

VISUAL BASIC

RemoveHandler Form1.Click, AddressOf ClickEventHandler

See Also

-= Assignment Operator

-> Member Access Operator

Visual Basic does not include direct support for pointer operations, and therefore does not provide access to type members through pointer dereferencing.

VISUAL BASIC

value = element.OneMember  ' Standard member access

value = element!OneName    ' Dictionary member access

value = element("OneName") ' Dictionary member access

See Also

. Member Access Operator, [ ] Member Access Operator, Pointers

. Member Access Operator

Both C# and Visual Basic employ a dotted member-access syntax using the period (.) between namespace, class, instance, and member names.

C#

value = element.OneMember;

VISUAL BASIC

value = element.OneMember

/ Division Operator

C# defines a single operator that handles numeric division for both integer and floating-point values (and for other types when used with operator overloading).

C#

int wholeResult1 = 5 / 3;    // 1

int wholeResult2 = 6 / 3;    // 2

float realResult = 5f / 3f;  // 1.666666...

The return type in C# generally follows the type of the operands. The operands are coerced into the same type when needed before the division takes place. This is true for integer and floating-point values. For integer division, rounding always leans toward zero.

Visual Basic also includes a division operator. Unlike C#’s operand-directed return type, the / operator in VB always returns a floating-point quotient.

VISUAL BASIC

Dim wholeResult1 As Double = 5 / 3   ' 1.666666...

Dim wholeResult2 As Double = 6 / 3   ' 2.0

Dim realResult As Single = 5! / 3!   ' 1.666666...

In most cases, VB’s division operation returns a result of type Double, even with integer operands. If one operand is Single and the other is non-Double, the result is Single. If one operand is Decimal and the other is anything other than Single or Double, the result isDecimal.

Visual Basic also has a \ integer division operator. When used in place of /, the result is always an integer value, with rounding toward zero.

VISUAL BASIC

Dim wholeResult1 As Integer = 5 \ 3  ' 1

Dim wholeResult2 As Integer = 6 \ 3  ' 2

Dim realResult As Long = 5! \ 3!     ' 1

Floating-point values are coerced to the Long data type before processing, and rounded using banker’s rounding (0.5 values are rounded toward the nearest even integer). If Option Strict On is used, you must manually coerce floating-point values to an appropriate integer type (Byte , Short, Integer, or Long).

Both languages follow the same divide-by-zero rules for the / operator, with an exception thrown for Decimal operands, and System.Double.NaN returned for other data types. For VB’s \ operator, divide-by-zero always throws an exception.

/* */ Comment Delimiters

Visual Basic does not include a delimited comment style. Comments always begin with a single quote (') or the REM statement and continue to the end of the current physical line. To continue a comment on the next line, start the subsequent line with another comment symbol.

C#

/* ----- This is a

 *       multiline comment.

 */

VISUAL BASIC

' ----- This is an attempt at a

'       multiline comment.

C#’s delimited comments also allow you to insert a comment in the middle of a statement.

C#

if (/* Annual */ salary >= 100000)

This syntax has no equivalent in Visual Basic.

// Comment Symbol

The Visual Basic equivalent of C#’s // comment symbol is the single quote ('). Both symbols start a comment that continues to the end of the current physical line.

C#

// ----- This is a full-line comment.

result = DoWork();  // A trailing comment.

VISUAL BASIC

' ----- This is a full-line comment.

result = DoWork()  ' A trailing comment.

New with Visual Studio 2015

Trailing comments in C# can appear in the middle of a logical line. Such uses are permitted in Visual Basic starting with its 2015 release, but not before.

C#

result = DoWork(firstArgument,  // Always allowed in C#

    secondArgument);

VISUAL BASIC

result = DoWork(firstArgument,  ' VB 2015 and later only

    secondArgument)

Visual Basic also includes a REM statement that is similar in purpose to the single-quote symbol. Its use in modern VB code is rare.

VISUAL BASIC

REM ----- This is an old-style comment. Avoid it.

See Also

XML Documentation Comments

/// XML Documentation Comment Symbol

See

XML Documentation Comments

/= Assignment Operator

Visual Basic’s /= assignment operator is similar to the same operator in C#, although the data types returned differ between the two languages. In general, C# retains the most relevant operand type, while in VB, the result is always Double or Decimal.

C#

originalValue /= 5.2;

VISUAL BASIC

originalValue /= 5.2#  ' # suffix indicates Double

Visual Basic also includes a \= assignment operator that performs integer division instead of a floating-point operation.

VISUAL BASIC

originalInteger \= 5

See the “/ Division Operator” entry in this chapter for full information on the differences between the C# and Visual Basic division operators.

See Also

/ Division Operator, Assignment Operators

: Base Declaration Indicator

In C#, classes and interfaces from which a type inherits appear in the declaration, separated from the type name by a colon.

C#

public class Dog : Animal, IDomesticate { }

In Visual Basic, a type identifies these underlying sources through the Inherits and Implements statements. For base types, the Inherits statement appears on the line immediately after the type definition. You can also use VB’s : statement separation symbol to attach the Inherits statement to the end of the class declaration’s physical line. This results in a more C#-like appearance, although it is not a common practice.

VISUAL BASIC

' ----- Standard syntax.

Public Class Dog

    Inherits Animal

End Class

' ----- Syntax using : symbol.

Public Class Dog : Inherits Animal

End Class

Interfaces implemented by the new type appear in the Implements statement as a comma-delimited list. As with the Inherits statement, the Implements statement appears immediately after the opening of the type declaration. When a class needs both a base type and one or more interfaces, the Inherits statement comes before the Implements statement.

VISUAL BASIC

Public Class Dog

    Inherits Animal

    Implements IDomesticate

    ' ----- The rest of the class appears here.

End Class

Interface inheritance in VB uses the Inherits statement within the new interface declaration. For structures that implement an interface, use the Implements statement.

VISUAL BASIC

Interface IHuman

    Inherits ILifeform

End Interface

Structure Person

    Implements IHuman

End Structure

When a C# class or structure implements an interface member, it does so implicitly via the name and argument signature, or explicitly by including the interface name in the method definition.

C#

interface IDomesticate

{

    void Train(int daysRequired);

}

class Dog : IDomesticate

{

    // ----- Implicit implementation.

    public void Train(int daysRequired) { }

    // ----- Explicit implementation.

    public void IDomesticate.Train(

        int daysRequired) { }

}

In Visual Basic, all interface member implementations must be declared explicitly, and require the Implements clause as part of the method declaration.

VISUAL BASIC

Interface IDomesticate

    Sub Train(ByVal daysRequired As Integer)

End Interface

Class Dog

    Implements IDomesticate

    Public Sub Train(ByVal daysRequired As Integer) _

            Implements IDomesticate.Train

        ' ----- Implementation code here.

    End Sub

End Class

One advantage (or disadvantage, depending on your perspective) of this syntax is that, in Visual Basic, the name of the implementing member need not be the same as the interface member being implemented.

VISUAL BASIC

Public Sub TeachTheDog(ByVal daysRequired _

    As Integer) Implements IDomesticate.Train

This ability to change the implementation name is not supported in C#.

: Named Argument Indicator

When using named arguments in method calls, Visual Basic uses the := named argument indicator in the same way that C# employs the equivalent : indicator.

C#

DefineAbbreviation(fullName:"Montana", shortName:"MT");

VISUAL BASIC

DefineAbbreviation(fullName:="Montana", shortName:="MT")

As in C#, named arguments in VB can follow earlier positional arguments, but a positional argument cannot follow a named argument.

VISUAL BASIC

' ----- This syntax is valid...

ProcessData(Date.Today, batchID:="12345")

' ----- ...but this is not.

ProcessData(batchID:="12345", Date.Today)

See Also

, Punctuator, Arguments and Parameters

:: Namespace Alias Qualifier

In C#, the global:: prefix indicates that some fully qualified namespace, type, or member name starts at the root of the namespace hierarchy, removing ambiguity between similarly named library members.

C#

// ----- Perhaps you defined a MyApp.System.Exception

//       class in your application's code. This makes

//       it clear you want .NET's Exception class.

global::System.Exception theProblem;

In Visual Basic, use Global as the first component of the fully qualified type or member path to make it clear that the path begins at the namespace root.

VISUAL BASIC

Dim theProblem As Global.System.Exception

In C#, you can define other namespace aliases that can appear in place of “global.” This allows your code to reference methods from external assemblies, when used in conjunction with the extern alias statement. This use of the namespace alias qualifier has no equivalent in Visual Basic.

; Statement Termination Character

Complete C# statements end with the ; statement termination character, allowing a single statement to flow across as many lines as desired. In Visual Basic, statements terminate at the end of a physical line, unless there is some indication that the statement must continue onto the next physical line.

VISUAL BASIC

result = DoSomeWork(withThisData) ' <-- Ends here

The traditional VB way to continue a statement onto a subsequent line is to end the physical line with the _ line continuation character (with at least one space character before it).

VISUAL BASIC

result = DoSomeWork(withThisData) _

    + SomeExtraWork(withMoreData)

Visual Basic 2010 introduced implicit line continuation, where the syntax of the statement provides hints as to whether a line will continue onto the next physical line. For instance, ending a line with a comma from an argument list indicates that the remaining arguments are on the next line.

VISUAL BASIC

result = DoAdvancedWork(withThisData,

    evenMoreData)

Implicit line continuation only works when it is clear to the Visual Basic compiler that a physical line ends in the middle of the statement. Typically, this involves ending a line with an operator, or leaving a set of incomplete parentheses open, among other actions.

VISUAL BASIC

' ----- These split lines require explicit

'       line continuation.

result = 3 _

    + 5

value = someObject _

    .Member

' ----- These split lines are continued implicitly.

result = 3 +

    5

value = someObject.

    Member

In some cases, Visual Basic permits multiple statements to appear on a single physical line. Separate the statements with the : statement separation symbol. Typically, such statements are added to the end of a single-line If statement, allowing two statements to be processed based on a single Boolean condition.

VISUAL BASIC

If (problemMessage) Then _

    RecordError(problemMessage) : Return

< > Generic Type Placeholder

In Visual Basic, the type of a generic declaration appears in parentheses with an Of clause.

C#

Dictionary<long, string> lookupSet;

VISUAL BASIC

Dim lookupSet As Dictionary(Of Long, String)

This syntax extends to class definitions, and anywhere else C# would normally place the type placeholder in angle brackets.

See Also

Generics

< Comparison Operator

When comparing value types, Visual Basic’s < operator is identical to C#’s < operator, and appears in the same binary-operator position.

C#

if (teamPlayers < 9)

VISUAL BASIC

If (teamPlayers < 9) Then

For string comparisons, C# and VB default to the same method of comparison, checking the binary value of each character in the string. However, VB’s Option Compare Text statement, when used within a project or source file, causes the comparison to use culture-specific text sorting rules.

<< Left Shift Operator

Visual Basic’s << operator is identical in syntax and usage to C#’s << operator.

<<= Assignment Operator

Visual Basic’s <<= operator is identical in syntax and usage to C#’s <<= operator.

See Also

Assignment Operators

<= Comparison Operator

Visual Basic’s <= operator is generally the same as C#’s <= operator. The entry for the < operator has additional information about string comparisons.

See Also

< Comparison Operator

= Assignment Operator

When used in a stand-alone assignment statement, Visual Basic’s = operator is identical in syntax and purpose to the = operator in C#.

C#

taxAmount = subtotal * taxRate;

VISUAL BASIC

taxAmount = subtotal * taxRate

C# allows an assignment to occur within an expression, or multiple assignments to occur within a single statement.

C#

// ----- latestValue will be updated before

//       the method call.

ProcessValue(latestValue = incomingValue);

// ----- All three variables will have c's value.

a = b = c;

Neither of these forms exists in Visual Basic; you must perform each assignment in a separate statement in VB.

See Also

Assignment Operators

== Comparison Operator

When comparing value types, Visual Basic’s = equality operator is identical to C#’s == operator, and appears in the same binary-operator position.

C#

if (teamPlayers == 9)

VISUAL BASIC

If (teamPlayers = 9) Then

For string comparisons, the = operator also replicates C#’s == operator. However, VB’s Option Compare statement impacts the way that strings compare to each other. By default, both C# and Visual Basic perform binary-level comparisons of strings. However, if a VB project or source file employs Option Compare Text, the comparison instead uses culture-specific text sorting rules.

For reference types other than strings, C#’s == operator tests whether the two references being compared refer to the same underlying instance. This syntax is invalid in Visual Basic (at least when Option Strict On is used). Instead, VB programs use the Is operator with a second instance, or with Nothing.

C#

// ----- Standard instance comparison.

if (firstIntance == secondInstance)

// ----- Comparisons with null.

if (anotherInstance == null)

VISUAL BASIC

' ----- Standard instance comparison.

If (firstInstance Is secondInstance) Then

' ----- Comparisons with null (Nothing in VB).

If (anotherInstance Is Nothing) Then

=> Lambda Operator

Visual Basic includes lambda expressions and anonymous functions that parallel the same features in C#. Single-line lambda expressions in both languages are quite similar, although the VB version does not require any specific replacement for the => lambda operator.

C#

// ----- NOTE: These expressions are not meant to

//       be used alone, but are shown here out of

//       context for demonstration purposes only.

// ----- With typed arguments.

(int limit, string code) => code.Length > limit

// ----- With inferred arguments.

(first, second) => first != second

// ----- With no arguments.

() => LogAction()

VISUAL BASIC

' ----- With typed arguments.

Function(ByVal limit As Integer,

    ByVal code As String) code.Length > limit

' ----- With inferred arguments.

Function(first, second) first <> second

' ----- With no arguments, and no return value.

Sub() LogAction()

Multiline anonymous functions in C# use a set of curly braces after the => operator. In Visual Basic, the same thing is accomplished by starting the function logic on the line following the argument list, and ending the block with End Sub or End Function .

C#

(int someArgument) =>

{

    // ----- Code appears here.

};

VISUAL BASIC

Sub(ByVal someArgument As Integer)

    ' ----- Or Function...End Function.

End Sub

Anonymous functions in both languages can be asynchronous by preceding the entire expression with async (C#) or Async (Visual Basic).

New with Visual Studio 2015

In 2015, C# added the ability to define method, property, and indexer members in a type using lambda expressions.

C#

// ----- Method.

public Position Move(int xOffset, int yOffset) =>

    new Position(CurrentX + xOffset, CurrentY + yOffset);

// ----- Read-only property.

public string FileAs => LastName + ", " + FirstName;

// ----- Indexer.

public Order this[long orderID] =>

    LookupOrderByID(orderID);

This use of lambda expressions does not yet exist in Visual Basic.

In C#, older-style anonymous functions use the delegate keyword to begin an anonymous function block. In Visual Basic, there is no differentiation between anonymous functions and lambda expressions in terms of syntax. The Sub lambda expression in VB is the closest equivalent for delegate when creating inline event handlers. See the “delegate Statement” entry in this chapter for an example.

> Comparison Operator

When comparing value types, Visual Basic’s > operator is identical to C#’s > operator, and appears in the same binary-operator position.

C#

if (teamPlayers > 9)

VISUAL BASIC

If (teamPlayers > 9) Then

The entry for the < operator has additional information about string comparisons.

>= Comparison Operator

Visual Basic’s >= operator is generally the same as C#’s >= operator. The entry for the < operator has additional information about string comparisons.

See Also

> Comparison Operator

>> Right Shift Operator

Visual Basic’s >> operator is identical in syntax and usage to C#’s >> operator.

>>= Assignment Operator

Visual Basic’s >>= operator is identical in syntax and usage to C#’s >>= operator.

See Also

Assignment Operators

? Nullable Type Indicator

See

Nullable Types

?. Null Conditional Operator

New with Visual Studio 2015

In 2015, both C# and Visual Basic added a set of null conditional operators. In general, they are used in exactly the same way between the languages, but with slight differences in syntax.

Usage

C# Syntax

Visual Basic Syntax

Instance Member

A?.B

A?.B

Dictionary Member

Not supported

A?!B

Array or Indexed Member

A?[B]

A?(B)

XML Attribute Axis

Not supported

A?.@B

XML Child Axis

Not supported

A?.<B>

XML Descendant Axis

Not supported

A?...<B>

?: Conditional Operator

In Visual Basic, the conditional operator—traditionally called the ternary operator—has a method-call syntax using the If operator. Its syntax varies from C#’s ?: operator, but it produces the same results.

C#

string result = amount > 100 ? "Overflow" :

    amount.ToString();

VISUAL BASIC

Dim result As String = If(amount > 100, "Overflow",

    amount.ToString())

The If operator accepts three arguments: (1) a Boolean test condition, (2) the value to return if the condition is true, and (3) the value to return if the condition is false. As in C#, the If operator short-circuits; either the true or false part is evaluated, but not both.

Visual Basic also includes an older IIf function that is somewhat similar to the newer If operator, and has the same syntax. However, IIf is not short-circuiting, and its return value is always of type System.Object.

C#’s conditional operator is right-associative. Consider the following expressions, which are all equivalent.

C#

result1 = a ? b : c ? d : e;

result2 = a ? b : (c ? d : e);

VISUAL BASIC

result1 = If(a, b, If(c, d, e))

?? Coalescence Operator

The ?? operator returns a value if that value is non-null, or an alternate second value if that first value is in fact null.

C#

// ----- Using a domain-specific default.

//       Assumes: string suppliedName;

string customerName = suppliedName ?? "Customer";

// ----- Using default for a nullable type.

//       Assumes: int? countFromUser;

int startingValue = countFromUser ?? default(int);

In Visual Basic, use the If operator with two arguments to defer to a second value when the first is Nothing.

VISUAL BASIC

' ----- Using a domain-specific default.

'       Assumes: Dim suppliedName As String

Dim customerName As String = If(suppliedName, "Customer")

' ----- For nullable value types, you must apply

'       a full conditional statement. Assumes:

'         Dim countFromUser As Integer?

Dim startingValue As Integer

If (countFromUser Is Nothing) Then

    startingValue = Nothing  ' Will become zero

Else

    startingValue = countFromUser

End If

@ Verbatim Indicator

C# uses the @ verbatim indicator to give guidance to the compiler when dealing with identifiers and strings. For identifiers, the symbol allows the term that follows it to be treated as an identifier, even if that term conflicts with a C# language keyword.

C#

int @double = originalValue * 2;

To qualify such names in Visual Basic, enclose them in a set of square brackets.

VISUAL BASIC

Dim [Double] As Integer = originalValue * 2

The set of keywords differs between the two languages, and a term that may require verbatim qualification in one language can work without it in the other. When doing cross-language development, take care to avoid keywords in both languages.

Because of C#’s case-sensitivity for identifiers, a term that may conflict with a lowercase language keyword will not conflict when entered using uppercase characters. A term that requires verbatim qualification in Visual Basic does so whether it is upper or lower case.

When placed before a C# string, the @ verbatim indicator tells the C# compiler to treat the string more literally. Such strings treat backslashes (\) as ordinary characters; there are no escape sequences in verbatim strings. Within such strings, use a pair of double-quote symbols to embed a lone double-quote within the text.

C#

string standard = "C:\\folder\\file.txt";

string verbatim = @"C:\folder\file.txt";

string notice = @"This string contains a ""quote.""";

Visual Basic only includes one type of string, one that is identical with C#’s verbatim strings. Strings in VB do not support escape sequences.

VISUAL BASIC

Dim standard As String = "C:\folder\file.txt"

Dim notice As String = "This string contains a ""quote."""

See Also

Identifiers, Literals

[ ] Array Declaration

Arrays are similar in their use between C# and Visual Basic, but there are differences in how they are declared.

C#

// ----- Uninitialized array.

int[] numberSet;

string[] textSet;

// ----- Initialized by size.

int[] setOfFive = new int[5];

// ----- Initialized by members.

string[] setOfThree = {"zero", "one", "two"};

VISUAL BASIC

' ----- Uninitialized array.

Dim numberSet() As Integer

Dim textSet() As String

' ----- Initialized by size.

Dim setOfFive(4) As Integer

' ----- Initialized by members.

Dim setOfThree() As String = {"zero", "one", "two"}

C# uses square brackets to indicate array elements. In Visual Basic, parentheses are used instead. Array declarations in C# always place the brackets with the type; VB allows the parentheses to be with the type or the identifier, but no size is allowed when the parentheses are attached to the type name.

VISUAL BASIC

' ----- Both of these will work.

Dim numberSetA() As Integer

Dim numberSetB As Integer()

When specifying an array size during declaration, C#’s syntax indicates the number of elements, while Visual Basic’s syntax specifies the upper bound of the array. To make it clear that the bound is used, VB includes the optional 0 To prefix. In both languages, the first array element is always numbered zero (0).

VISUAL BASIC

' ----- Both of these declare an array of elements

'       numbered from 0 to 4.

Dim setOfFiveA(4) As Integer

Dim setOfFiveB(0 To 4) As Integer

As with C#, Visual Basic supports both multidimensional arrays and jagged arrays.

C#

int[,] multiArray;

int[][] jaggedArray;

VISUAL BASIC

Dim multiArray(,) As Integer

Dim jaggedArray()() As Integer

Once an array exists in Visual Basic, whether initialized or not, the ReDim statement resizes the array, optionally preserving existing elements via the Preserve modifier.

VISUAL BASIC

Dim storageArea() As Integer  ' Uninitialized

' ----- Initialize the array to include 5 elements,

'       possibly wiping out any existing data.

ReDim storageArea(0 to 4)

' ----- Resize the array to include 10 elements,

'       preserving the existing 0 to 4 elements.

ReDim Preserve storageArea(0 to 9)

Member access is the same in both languages, with the exception of the brackets used.

C#

int thirdElement = largerArray[2];

VISUAL BASIC

Dim thirdElement As Integer = largerArray(2)

Size requests are also the same, through the Length, GetUpperBound, and GetLowerBound members. Visual Basic also includes two intrinsic functions, UBound and LBound, which return the limits.

C#

size = someArray.Length;

lower = someArray.GetLowerBound(0);

upper = someArray.GetUpperBound(0);

VISUAL BASIC

size = someArray.Length

lower = someArray.GetLowerBound(0)

upper = someArray.GetUpperBound(0)

' ----- Using VB's intrinsic functions. The second

'       argument is optional, defaulting to zero.

lower = LBound(someArray)

upper = UBound(someArray)

' ----- For a multidimensional array, get

'       second-rank bounds.

lower = LBound(multiArray, 1)

upper = UBound(multiArray, 1)

See Also

Arrays, Initialization

[ ] Attribute Usage Delimiter

Visual Basic surrounds attributes with angle brackets instead of C#’s square brackets.

C#

[System.Serializable]

public class EmployeeData

VISUAL BASIC

<System.Serializable>

Public Class EmployeeData

See Also

Attributes

[ ] Member Access Operator

Dictionary member access is fairly similar in both languages, with Visual Basic using a set of parentheses in lieu of C#’s square brackets.

C#

fullName = customerRecord["FullName"];

VISUAL BASIC

fullName = customerRecord("FullName")

Visual Basic also includes a syntax variation that uses an exclamation point to separate the dictionary instance from the member name.

VISUAL BASIC

fullName = customerRecord!FullName

See Also

this Indexer Declaration

\ Escape Sequence Indicator

See

Literals

\u Unicode Escape Sequence Indicator

See

Literals

^ Exclusive-Or Operator

Visual Basic’s Xor operator is an exact replacement for C#’s ^ exclusive-or operator, both for integer and Boolean operands.

C#

currentState = currentState ^ newInput;

VISUAL BASIC

currentState = currentState Xor newInput

Visual Basic includes a ^ operator, but it is used for exponentiation, the raising of a numeric value to a power.

^= Assignment Operator

Visual Basic does not include an equivalent for C#’s ^= operator. You must perform the exclusive-or (Xor) and assignment operations separately in VB.

C#

currentState ^= newInput;

VISUAL BASIC

currentState = currentState Xor newInput

Visual Basic includes a ^= operator, but it is used as that language’s Exponentiation assignment operator.

See Also

Assignment Operators

{ } Block Statement

In C#, any block of two or more statements that are subordinate to another statement must appear in a set of curly braces.

C#

if (warningMessage.Length > 0)

{

    RecordError(warningMessage);

    return -1;

}

Visual Basic uses block statements, such as If...End If to accomplish the same thing.

VISUAL BASIC

If (warningMessage.Length > 0) Then

    RecordError(warningMessage)

    Return -1

End If

Any variables declared within a subordinate block are scoped to that block. In C#, you can start a new scoping block at any time by opening a new set of curly braces.

C#

// ----- Nothing much going on here, then suddenly...

{

    // ----- Any variables declared here are scoped

    //       to the set of curly braces.

}

Visual Basic does not have an equivalent syntax for this scoping construct.

See Also

Lifetime and Scope

{ } Instance Initialization

See

Initializers

| Disjunction Operator

In general, Visual Basic’s Or operator is identical to C#’s | operator, both for integer (bitwise) and Boolean (logical) operations.

C#

bool complain = (hot | humid);

VISUAL BASIC

Dim complain As Boolean = (hot Or humid)

When applying Option Strict Off to a Visual Basic project or source file, using the Or operator with one integer operand and one Boolean operand forces the Boolean value to an integer (0 or ‑1), and then performs a bitwise operation. C# does not allow this mixture of operand types.

|= Assignment Operator

Visual Basic does not include an equivalent for C#’s |= operator. You must perform the disjunction (Or) and assignment operations separately in VB.

C#

daysOpen |= mondayFlag;

VISUAL BASIC

daysOpen = daysOpen Or mondayFlag

See Also

Assignment Operators

|| Disjunction Operator

Visual Basic’s OrElse operator is identical to C#’s || short-circuiting disjunction operator.

C#

if ((result == null) || (result.Length == 0))

VISUAL BASIC

If ((result Is Nothing) OrElse

    (result.Length == 0)) Then

~ Bitwise Complement Operator

The Visual Basic equivalent for C#’s ~ bitwise operator is the Not operator.

C#

int complement = ~originalValue;

VISUAL BASIC

Dim complement As Integer = Not originalValue

The Not operator is also a logical negation operator when used with Boolean operands. The equivalent in C# for that variation is the ! operator.

See Also

! Negation Operator

~ Destructor Prefix

See

Destructors

abstract Modifier

When applied to a class, Visual Basic’s MustInherit modifier is equivalent to C#’s class-bound abstract modifier.

C#

abstract class Creature

{

    // ----- Include members marked as abstract.

}

VISUAL BASIC

MustInherit Class Creature

    ' ----- Include members marked as MustOverride.

End Class

When applied to class members, C#’s abstract modifier is the same as Visual Basic’s MustOverride modifier. The decorated member will not include an implementation.

C#

// ----- Abstract method.

public abstract void ProcessResults();

// ----- Abstract property.

public abstract int MaxLevel { get; set; }

// ----- Abstract read-only indexer.

public abstract string this[int index] { get; }

VISUAL BASIC

' ----- Abstract method.

Public MustOverride Sub ProcessResults()

' ----- Abstract property.

Public MustOverride Property MaxLevel() As Integer

' ----- Abstract read-only indexer.

Public MustOverride Default ReadOnly Property Item(

    ByVal index As Integer) As String

C#’s abstract member modifier can be applied to methods, properties, indexers, and events. In Visual Basic, the MustOverride modifier can be applied to methods and properties, but not events. Just as C# abstract members can only appear in a class marked withabstract, Visual Basic MustOverride members can only appear in a MustInherit class.

Access Modifiers

Visual Basic includes access modifiers that parallel those found in C#.

C# Modifiers

Visual Basic Modifiers

internal

Friend

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

In most cases, the use of these modifiers in Visual Basic is identical to how they are used in C#, appearing as a prefix to the type or member being declared.

C#

public class Student

VISUAL BASIC

Public Class Student

When declaring fields within types using Visual Basic’s Dim statement, the access modifier appears as a prefix to the declaration.

VISUAL BASIC

Class NameTracking

    Private Dim OriginalName As String

However, it is more common to omit the Dim keyword in this declaration. In fact, Visual Studio automatically removes the Dim keyword in field definitions, retaining it only for local variables.

VISUAL BASIC

Class NameTracking

    Private OriginalName As String

Structure members may not use the protected (C#) or Protected (VB) modifier. For more information on using access modifiers, see the specific statements that employ access modifiers (such as “class Statement”) in this chapter.

Anonymous Methods

Visual Basic does not differentiate between anonymous methods and lambda expressions as C# does. See the “=> Lambda Operator” entry in this chapter for information on creating lambda expressions in Visual Basic.

Anonymous Types

C# uses the new operator to define a new anonymous type.

C#

var samplePerson = new {Name = "John", Age = 42};

Visual Basic uses a similar syntax, with the New and With operators used together. Each field within the type begins with a period (.).

VISUAL BASIC

Dim samplePerson = New With {.Name = "John",

    .Age = 42}

VB also allows you to specify which anonymous type properties are “key” properties, those that can be used for testing for equivalence between two instances.

VISUAL BASIC

Dim samplePerson = New With {Key .ID = 123,

    .Name = "John", .Age = 42}

See Also

Initializers, new Operator

Arguments and Parameters

Parameters are identifiers that are defined with a method, and through which data can be passed into that method. Arguments are the data elements or variables passed through the parameters when the method is called.

C#

// ----- Parameters: hour and minute.

public string FormatTime(int hour, int minute)

{

    return string.Format("{0:0}:{1:00}",

        hour, minute);

}

// ----- Later, arguments are passed to the method.

businessStart = FormatTime(5, 30);

Both C# and Visual Basic support similar features for working with parameters and arguments. By default, all comma-delimited arguments are passed by-value into the matching parameters. To change this default in C#, use the ref or out modifier. In Visual Basic, use the ByRef modifier to pass by-reference. In C#, the data type for each parameter appears just before the identifier. VB places the data type in an As clause just after the identifier.

C#

// ----- Parameters are:

//         content:  in/out by-reference

//         method:   by-value

//         warnings: out-only by-reference

public bool CorrectContent(ref string content,

    int method, out string warnings)

VISUAL BASIC

' ----- Parameters are:

'         content:  in/out by-reference

'         method:   by-value

'         warnings: in/out by-reference

Public Function CorrectContent(

    ByRef content As String,

    ByVal method As Integer,

    ByRef warnings As String)

Visual Basic does not have an equivalent for the out modifier; use ByRef instead, as you would use when replacing ref. When passing values by-reference, the calling code must have already assigned a value to the argument being passed. In C#, the calling code applies the out or ref modifier to match the one in the parameter list. Visual Basic requires no such modifier.

C#

// ----- userContent must have been assigned a value.

success = CorrectContent(ref userContent,

    3, out warningText);

VISUAL BASIC

' ----- userContent must have been assigned a value.

success = CorrectContent(userContent, 3, warningText)

Both languages support optional arguments and parameter arrays. See the “Optional Arguments” and “params Modifier” entries in this chapter. Named arguments are also valid in both languages. See the “: Named Argument Indicator” entry in this chapter.

See Also

, Punctuator, Methods, : Named Argument Indicator, Optional Arguments, out Modifier, params Modifier, ref Modifier

Arrays

See

[ ] Array Declaration

as Conversion Operator

C#’s as conversion operator is similar to a standard cast, but it returns null instead of throwing an exception if the conversion fails.

C#

Manager boss = employeeRecord as Manager;

In Visual Basic, when working with reference types, the TryCast operator performs a similar action, returning Nothing on failure.

VISUAL BASIC

Dim boss As Manager = TryCast(employeeRecord, Manager)

For value types, you need to use one of the intrinsic conversion expressions (such as CInt), the CType expression, or use one of the TryParse methods exposed by the target type (Integer.TryParse). This last option is the closest match for the as operator, as it indicates a Boolean success code instead of throwing an exception on a failed conversion.

See Also

Conversion and Casting

assembly Modifier

See

Attributes

Assignment Operators

Both C# and Visual Basic include multiple assignment operators, each applying a specific operation to the right-hand value before assigning it to the left hand result.

Operator

C#

Visual Basic

Addition

+=

+=

Assignment

=

=

Concatenation

+=

&=

Conjunction

&=

Not supported

Disjunction

|=

Not supported

Division

/=

/=

Event Subscription

+=

Not supported

Event Unsubscription

-=

Not supported

Exclusive-Or

^=

Not supported

Exponentiation

Not supported

^=

Integer Division

Not supported

\=

Left-Shift

<<=

<<=

Modulo

%=

Not supported

Multiplication

*=

*=

Right-Shift

>>=

>>=

Subtraction

-=

-=

For information about these operators, see their entries in this chapter.

C# allows multiple occurrences of assignment operators in a single statement.

C#

// ----- Both b and c receive a's value.

int a = 5, b = 10, c = 15;

c = b = a;

// ----- This more unusual use of assignment

//       is still valid.

int d = 5, e = 10, f = 15;

f -= e -= d;

// Result: d-->5, e-->5, f-->10

Visual Basic does not permit more than one assignment operator per statement.

Associativity

See

Operator Precedence and Associativity

async Modifier

Visual Basic’s Async modifier is identical in use and purpose to C#’s async modifier, for both standard and anonymous methods.

C#

public async Task<int> ProcessBuffer()

{

    // ----- At least one await appears in code.

}

VISUAL BASIC

Public Async Function ProcessBuffer() _

        As Task(Of Integer)

    ' ----- At least one Await appears in code.

End Function

See Also

await Operator

Asynchronous Processing

See

async Modifier, await Operator

Attributes

Both C# and Visual Basic allow attributes to be attached to types, members, or an entire assembly. C# attributes appear in square brackets; VB uses angle brackets. In both languages, if the defined attribute name ends in “Attribute,” that portion can be left off when using the attribute.

C#

[System.Obsolete("Use Creature Class Instead")]

class Animal

{

}

VISUAL BASIC

<System.Obsolete("Use Creature Class Instead")>

Class Animal

End Class

In both languages, multiple attributes can appear in separate sets of brackets, or separated by commas within a single set of brackets. When an attribute accepts arguments, you can specify named arguments or initializers with an = sign in C#, or := in Visual Basic.

C#

[AttributeUsage(AttributeTargets.Class,

    AllowMultiple=true)]

VISUAL BASIC

<AttributeUsage(AttributeTargets.Class,

    AllowMultiple:=True)>

Normally, an attribute appears just before the item it modifies. In some cases, it may be necessary to specify the target of the attribute. In both languages, indicate the target with a prefix immediately after the opening bracket.

C#

// ----- This attribute is for the whole assembly.

[assembly: AssemblyVersion("1.0.0.0")]

VISUAL BASIC

' ----- This attribute is for the whole assembly.

<Assembly: AssemblyVersion("1.0.0.0")>

C# supports more target prefixes than does Visual Basic. The following table lists the targets available as prefixes in both languages.

C#

Visual Basic

Applies to

assembly

Assembly

Entire assembly

module

Module

Current assembly module (not a VB Module)

field

Not supported

Type-level fields

event

Not supported

Events

method

Not supported

Methods, property getters or setters

param

Not supported

Method or property parameters

property

Not supported

Properties

return

Not supported

Return values for methods, indexers, or properties

type

Not supported

Classes, structures, interfaces, enumerations, or delegates

When a prefix is not available in VB, you can only associate it with the target by placing the attribute immediately before that target. For return values in Visual Basic, place the attribute between the As keyword and the data type that follows it in the method’s signature.

In addition to the targets listed in the table above, C# allows attributes to be attached to type placeholder variables in generic type declarations.

C#

public class FlexibleType<[CSharpOnly]T>

This is not supported in Visual Basic.

Automatic Properties

In C#, automatic properties (also known as “auto-implemented properties”) include the property declaration, but no getter or setter implementation.

C#

public string CoreName { get; set; }

This trimmed down version of a property is also used in Visual Basic to create automatic properties.

VISUAL BASIC

Public Property CoreName As String

New with Visual Studio 2015

C# lets you create read-only automatic properties. Before 2015, Visual Basic did not support read-only automatic properties. Instead, it was necessary to create a normal property with the ReadOnly modifier, and leave out the setter code. However, its 2015 release added support for read-only auto-properties.

C#

public string CoreName { get; }

VISUAL BASIC

' ----- Before the 2015 release.

Public ReadOnly Property CoreName() As String

    Get

        ' ----- Property-specific logic here.

    End Get

End Property

' ----- Starting with the 2015 release.

Public ReadOnly Property CoreName As String

New with Visual Studio 2015

Originally, C# did not allow automatic properties to be initialized as part of the declaration itself. In 2015, the language gained this functionality for both read-only and read-write properties. Visual Basic already included such initialization features for read-write auto-properties, but initialization of read-only automatic properties came about in that same 2015 release.

C#

// ----- Read-write property.

public string CoreName { get; set; } = "Unknown";

// ----- Read-only property.

public string CoreName { get; } = "Unknown";

VISUAL BASIC

' ----- Read-write property.

Public Property CoreName As String = "Unknown"

' ----- Read-only property.

Public ReadOnly Property CoreName As String = "Unknown"

Both languages now also permit assignment to read-only automatic properties within a constructor.

See Also

Properties

await Operator

Visual Basic’s Await operator is identical to C#’s await operator.

C#

// ----- The long version.

Task<string> theTask = SomeMethodAsync();

string result = await theTask;

// ----- The short version.

string result = await SomeMethodAsync();

VISUAL BASIC

' ----- The long version.

Dim theTask As Task(Of String) = SomeMethodAsync()

Dim result As String = Await theTask

' ----- The short version.

Dim result As String = Await SomeMethodAsync()

New with Visual Studio 2015

Starting in 2015, C#’s await operator can be used in the catch and finally blocks of a try statement, although this option is not yet supported in Visual Basic.

See Also

async Modifier

base Constructor Declaration

In C#, a base constructor can be called from a derived constructor as part of its declaration syntax.

C#

// ----- Assumes BaseClass with a default

//       constructor, plus a constructor that

//       accepts an int.

class DerivedClass : BaseClass

{

    public DerivedClass() : base()

    {

        // ----- Default constructor logic here.

    }

    public DerivedClass(int value) : base(value)

    {

        // ----- Constructor logic here.

    }

}

In Visual Basic, the call to the base class constructor occurs within the code of the constructor logic itself, using the MyBase access keyword.

VISUAL BASIC

' ----- Assumes BaseClass with a default constructor,

'       plus a constructor that accepts an Integer.

Class DerivedClass

    Inherits BaseClass

    Public Sub New()

        ' ----- Explicit call to base is optional.

        MyBase.New()

        ' ----- Default constructor logic here.

    End Sub

    Public Sub New(ByVal value As Integer)

        MyBase.New(value)

        ' ----- Constructor logic here.

    End Sub

End Class

See Also

Constructors, this Constructor Declaration

base Access Expression

Visual Basic’s MyBase expression provides the same type of access to base type members as does C#’s base expression.

C#

base.RefreshStatus();

VISUAL BASIC

MyBase.RefreshStatus()

Bitwise Operators

See

See Operators

bool Data Type

Visual Basic’s intrinsic Boolean data type is identical to C#’s bool data type. Both types are aliases for .NET’s System.Boolean type. For Boolean literals, C# uses true and false in all lowercase. Although VB is not case-sensitive, the traditional literals are True andFalse with an initial capital.

C#

bool finished = false;

VISUAL BASIC

Dim finished As Boolean = False

When converting or casting a Boolean value to an integer in C#, false always becomes 0 (zero), and true becomes 1 (one). In Visual Basic, False always becomes zero, as in C#. However, for historical reasons, True becomes 1 or -1 depending on the method used to convert or cast the value.

VISUAL BASIC

Dim byDotNet As Integer =

    Convert.ToInt32(True)                ' --> 1

Dim byIntrinsic As Integer = CInt(True)  ' --> -1

' ----- Next two require Option Strict Off

Dim byMath As Integer = Int(True)        ' --> 1

Dim byImplicit As Integer = True         ' --> -1

break Statement

C# uses a single break statement to exit immediately out of for, foreach, and do loops, and the switch statement.

C#

for (counter = 0; counter < 10; counter++)

{

    // ----- Some code, then...

    break;

    // ----- More code.

}

In place of break, Visual Basic uses one of four distinct forms of its Exit statement, depending on the containing construct.

·        For and For Each loops use the Exit For statement.

·        Do loops use the Exit Do statement.

·        While loops use the Exit While statement.

·        Select Case statements use the Exit Select statement.

VISUAL BASIC

For counter = 0 To 9

    ' ----- Some code, then...

    Exit For

    ' ----- More code.

Next counter

In C#, each case or default block within a switch statement requires at least one break statement (or similar exit construct) to confirm the end of block-specific logic.

C#

switch (sides)

{

    case 3:

        name = "Triangle";

        break;

    case 4:

        name = "Rectangle";

        break;

Visual Basic does not impose this requirement. The Exit Select is optional, and a Case block will always exit after the last logic line within its block.

VISUAL BASIC

Select Case sides

    Case 3

        name = "Triangle"

    Case 4

        name = "Rectangle"

byte Data Type

Visual Basic’s intrinsic Byte data type is identical to C#’s byte data type. Both types are aliases for .NET’s System.Byte type.

C#

byte smallCount = 1;

VISUAL BASIC

Dim smallCount As Byte = 1

case Clause

See

switch Statement

Casting

See

Conversion and Casting

catch Clause

See

try Statement

char Data Type

Visual Basic’s intrinsic Char data type is identical to C#’s char data type. Both types are aliases for .NET’s System.Char type. For char literals, C# surrounds a character with single quotes. In Visual Basic, the character appears in double quotes, and is followed by a csuffix.

C#

char digit = '1';

VISUAL BASIC

Dim digit As Char = "1"c  ' Or "1"C

checked Expression

C#’s checked keyword, whether in its statement-block form or expression form, enables run-time integer overflow checking on the contained statements or expression.

Visual Basic enables integer overflow checking by default on a project-wide basis. To enable or disable overflow checking, access the Advanced Compiler Settings within the Project Properties, and set the Remove Integer Overflow Checks field as needed. VB does not include the ability to control integer overflow checks at the statement or expression level.

class Statement

Visual Basic’s Class statement is equivalent to C#’s class statement. When declaring a derived class, VB’s Inherits clause follows the opening of the class declaration block. Likewise, when a class implements one or more interfaces, the Implements clause lists those interfaces, and appears at the top of the class, just after the Inherits clause if present.

C#

class ActiveCustomer : Customer, IDisposable

{

    // ----- Members appear here.

}

VISUAL BASIC

Class ActiveCustomer

    Inherits Customer

    Implements IDisposable

    ' ----- Members appear here.

End Class

Classes in both languages contain the same types of members: constructors, destructors, fields, constants, properties, methods, events, operator overloads and user-defined conversions, indexers (called “default properties” in VB), and nested types (including delegates and enumerations). Many of these members can exist as static or instance members.

Classes support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

abstract

MustInherit

internal

Friend

new

Shadows

partial

Partial

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

sealed

NonInheritable

static

Not supported

Classes in C# are internal by default, just as classes in Visual Basic are Friend by default. Within C# classes, all members are private by default. In Visual Basic, fields and constants are Private by default, while all other members are Public by default.

Visual Basic does not permit static classes (called “shared classes” in VB). Instead, a class with all static (shared) members must be created using the Module statement.

C#

static class UsefulFunctions

{

    public static string Reverse(string originalText)

    {

        char[] buffer;

        if (originalText == null)

            return "";

        else

        {

            buffer = originalText.ToCharArray();

            Array.Reverse(buffer);

            return new string(buffer);

        }

    }

}

VISUAL BASIC

Module UsefulFunctions

    Public Function Reverse(ByVal originalText _

            As String) As String

        Dim buffer() As Char

        If (originalText Is Nothing) Then

            Return ""

        Else

            buffer = originalText.ToCharArray()

            Array.Reverse(buffer)

            Return New String(buffer)

        End If

    End Function

End Module

See Also

Access Modifiers, Constructors, Destructors

Collection Initializers

See

Initializers

Comments

C# includes comments that terminate at the end of a physical line (those starting with the // symbol) and those that can cover any contiguous span of content, from a partial line to multiple lines (those delimited by /* and */ symbols).  Visual Basic only supports the first type, with the single quote symbol (') or the REM keyword.

VISUAL BASIC

REM This is a full-line comment.

' Another full-line comment.

Dim counter As Integer ' A line-ending comment

See Also

/* */ Comment Delimiters, // Comment Symbol, XML Documentation Comments

Compiler Constants

Both C# and Visual Basic include project-level support for the DEBUG and TRACE compiler constants. Code throughout the .NET Framework responds to these constants, and you can use them in your own code. To alter the default settings, set the Define DEBUG Constant and Define TRACE Constant fields as needed. In C#, these fields appear on the Project Properties’ Build tab; in VB, they appear in the Advanced Compile Options area of the Compile tab.

Although you can always define your own project-specific compiler constants, C# itself does not define any other constants by default. Visual Basic defines four (or up to nine) additional constants.

Constant

Description

CONFIG

The active build configuration, typically “Debug” or “Release.”

TARGET

The compiled application type, one of: “winexe,” “exe,” “library,” or “module.” Other custom values are also possible.

VBC_VER

The current version of Visual Basic, in major.minor format. One of the following values: 8.0 (VB2005), 9.0 (VB2008 and VB2010), 11.0 (VB2012), 12.0 (VB2013), or 14.0 (VB2015).

_MYTYPE

The version of the My pseudo-namespace in use. Depending on the value of this constant, the compiler may define one or more of the following additional constants: _MYAPPLICATIONTYPE , _MYCOMPUTERTYPE, _MYFORMS, _MYUSERTYPE, and _MYWEBSERVICES.

See Microsoft’s MSDN documentation for full information on these constants and how to use them in your code.

const Statement

Both Visual Basic and C# support the declaration of constants at the local and type levels. The syntax of C#’s const statement closely parallels standard variable declaration; VB’s syntax naturally follows its own variable declaration, replacing Dim with Const.

C#

const int DefaultPort = 25;

VISUAL BASIC

Const DefaultPort As Integer = 25

In both languages, you can string multiple constant declarations together with commas. The two languages also support similar rules on what can be assigned to a constant: literals, enumeration values, and other constants, all joined with basic operators. VB lets you use its intrinsic conversion functions (like CInt ) as well.

At the field level, each constant declaration can include an access modifier.

C#

public const int DefaultPort = 25;

VISUAL BASIC

Public Const DefaultPort As Integer = 25

If Option Infer On is used, Visual Basic will infer the data type of the expression when possible, removing the need for a specific type.

VISUAL BASIC

Const DefaultPort = 25

Some constant declarations are not permitted in C# due to boxing or other reference issues.

C#

// ----- This code will not compile:

const object usesBoxing = 10;

const object implicitReference = "Message";

Such declarations are permitted in Visual Basic.

Constructors

In C#, constructors are named for the type in which they appear. In Visual Basic, constructors are always named New. Constructors in both languages provide functionality that is generally equivalent.

C#

class Employee

{

    public Employee()

    {

        // ----- Default constructor.

    }

    public Employee(string empName)

    {

        // ----- Custom constructor.

    }

}

VISUAL BASIC

Class Employee

    Public Sub New()

        ' ----- Default constructor.

    End Sub

    Public Sub New(ByVal empName As String)

        ' ----- Custom constructor.

    End Sub

End Class

By default, the constructor in a derived class calls the default constructor in the base class, if it exists. To call a custom base constructor, or to use another custom constructor as the starting point for a constructor, use the base and this constructor declarations, respectively.

C#

class Employee : Person

{

    public Employee(string empName) : base(empName)

    {

        // ----- Base class handles person's name.

    }

    public Employee(string empName,

        decimal salary) : this(empName)

    {

        // ----- Salary-specific code here.

    }

}

In Visual Basic, these base and local constructor foundations are handled within the code of the constructor. Call the relevant base or local constructor as the first line of the new constructor.

VISUAL BASIC

Class Employee

    Inherits Person

    Public Sub New(ByVal empName As String)

        ' ----- Base class handles person's name.

        MyBase.New(empName)

    End Sub

    Public Sub New(ByVal empName As String,

            ByVal salary As Decimal)

        ' ----- Another constructor handles the name.

        Me.New(empName)

        ' ----- Salary-specific code here.

    End Sub

End Class

Both languages offer static constructors in addition to instance constructors.

C#

class Utility

{

    static Utility()

    {

        // ----- Static class initialization here.

    }

}

VISUAL BASIC

Class Utility

    Shared Sub New()

        ' ----- Static class initialization here.

    End Sub

End Class

Constructors support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

Extern

Not supported

Internal

Friend

Private

Private

protected

Protected

protected internal

Protected Friend

Public

Public

Static

Shared

See Also

base Constructor Declaration, this Constructor Declaration

continue Statement

C# uses a single continue statement to begin the next iteration of a loop construct.

C#

for (counter = 0; counter < 10; counter++)

{

    // ----- Some code, then...

    continue;

    // ----- More code.

}

Visual Basic uses one of three distinct forms of its Continue statement, depending on the containing loop type.

·        For and For Each loops use the Continue For statement.

·        Do loops use the Continue Do statement.

·        While loops use the Continue While statement.

VISUAL BASIC

For counter = 0 To 9

    ' ----- Some code, then...

    Continue For

    ' ----- More code.

Next counter

Because Visual Basic lets you identify a specific loop type, it is possible to move to the next iteration of a loop containing the innermost loop.

VISUAL BASIC

For counter As Integer = 0 To 9

    Do While (content.Length > 0)

        ' ----- This will exit the Do loop, and move

        '       to the next iteration of the For loop.

        Continue For

    Loop

Next counter

Conversion and Casting

C# supports both (1) implicit (widening) casting or conversion of data, such as from int to long; and (2) explicit casting or conversion of data with the () casting operator, the as operator, and .NET Framework features, such as those from the System.Convert class.

Implicit Conversions

Conversions from “smaller” to “larger” data types, including overloaded conversions defined as implicit (C#) or Widening (VB), occur automatically in both languages.

C#

int smallValue = 25;

long largeValue = smallValue;  // Implicit

VISUAL BASIC

Dim smallValue As Integer = 25

Dim largeValue As Long = smallValue  ' Widening

In Visual Basic, when the Option Strict Off statement is used at the file or project level, explicit (narrowing) conversions can also occur in code automatically, although run-time errors may result if the source data does not “fit” in the target.

VISUAL BASIC

' ----- At the top of the file.

Option Strict Off

' ----- In a method.

Dim largeValue As Long = 100000

Dim smallValue As Integer = largeValue  ' Narrowing

When using this non-strict mode, Visual Basic also performs some string-to-number and number-to-string conversions automatically, in ways not supported by C#.

VISUAL BASIC

' ----- Assumes: Option Strict Off

Dim trueNumber As Integer = "123"  ' Auto-conversion

Dim trueString As String = 123     ' Auto-conversion

If (trueNumber = trueString) Then

    ' ----- VB performs the conversion and comparison

    '       of the two variables automatically. The

    '       code will reach this conditional block.

End If

Explicit Conversions

Explicit casts in C# occur by using the () casting operator before an expression.

C#

long largeValue = 100000;

int smallValue = (int)largeValue;

For intrinsic value types, Visual Basic offers built-in conversion operators, such as CInt to convert an expression to an Integer. Internally, some of these operators provide additional type checking not found in standard C# casts. However, they are commonly used in Visual Basic in much the same way that C# programmers use the () cast operator.

VISUAL BASIC

Dim largeValue As Long = 100000

Dim smallValue As Integer = CInt(largeValue)

The following table lists the Visual Basic conversion operators, and shows how they relate to specific C# casts.

C# Cast

Visual Basic Conversion

(bool)

CBool(expression)

(byte)

CByte(expression)

(char)

CChar(expression)

(DateTime)

CDate(expression)

(double)

CDbl(expression)

(decimal)

CDec(expression)

(int)

CInt(expression)

(long)

CLng(expression)

(object)

CObj(expression)

(sbyte)

CSByte(expression)

(short)

CShort(expression)

(float)

CSng(expression)

(string)

CStr(expression)

(uint)

CUInt(expression)

(ulong)

CULng(expression)

(ushort)

CUShort(expression)

(type)

CType(expressiontype)

These Visual Basic operators are not exact replacements for the C# casts shown here. In many cases, each operator performs extra steps to ensure a conversion succeeds where it might fail in the equivalent C# code. For example, many of the numeric conversion operators will strip out currency symbols and grouping symbols silently. These characters would cause a failure in the equivalent C# cast.

C#

// ----- This will fail.

int trueNumber = (int)"$1,234";

VISUAL BASIC

' ----- This will succeed, resulting in 1234.

Dim trueNumber As Integer = CInt("$1,234")

Visual Basic’s CType operator is the most generic of the conversion operators, facilitating conversions between any two types that have a conversion defined. In fact, when defining overloaded conversions in VB, the declaration uses CType as the name for the conversion method.

For reference types that have a derived relationship, VB’s DirectCast operator is more casting-friendly, since it is able to make assumptions about the underlying data types involved in the cast.

VISUAL BASIC

' ----- Bring an elephant into the zoo.

Dim someElephant As Elephant

Dim someAnimal As Animal = GetNewAnimal()

If (TypeOf someAnimal Is Elephant) Then _

    someElephant = DirectCast(someAnimal, Elephant)

C#’s as operator is similar to casting, but it returns null when the conversion fails instead of throwing an exception. Visual Basic includes the TryCast operator, which produces similar Nothing results on failure.

C#

// ----- Might return null if conversion fails.

someElephant = someAnimal as Elephant;

VISUAL BASIC

' ----- Might return Nothing if conversion fails.

someElephant = TryCast(someAnimal, Elephant)

The .NET Framework includes features that convert data from one type to another. The System.Convert type hosts many such static functions. The following table shows System.Convert member substitutes for most of the VB conversion operators.

Visual Basic Conversion

System.Convert Method

CBool(expression)

ToBoolean(expression)

CByte(expression)

ToByte(expression)

CChar(expression)

ToChar(expression)

CDate(expression)

ToDateTime(expression)

CDbl(expression)

ToDouble(expression)

CDec(expression)

ToDecimal(expression)

CInt(expression)

ToInt32(expression)

CLng(expression)

ToInt64(expression)

CSByte(expression)

ToSByte(expression)

CShort(expression)

ToInt16(expression)

CSng(expression)

ToSingle(expression)

CStr(expression)

ToString(expression)

CUInt(expression)

ToUInt32(expression)

CULng(expression)

ToUInt64(expression)

CUShort(expression)

ToUInt16(expression)

The ToString method that is included with every .NET object is available equally in Visual Basic and C#.

Data Types

Visual Basic and C# share a common set of intrinsic data types, with one exception. The following table shows the matching data types, and the underlying .NET data type for which each intrinsic type is an alias.

C# Type

Visual Basic Type

.NET Type

bool

Boolean

System.Boolean

byte

Byte

System.Byte

char

Char

System.Char

decimal

Decimal

System.Decimal

double

Double

System.Double

float

Single

System.Single

int

Integer

System.Int32

long

Long

System.Int64

object

Object

System.Object

sbyte

SByte

System.SByte

short

Short

System.Int16

string

String

System.String

uint

UInteger

System.UInt32

ulong

ULong

System.UInt64

ushort

UShort

System.UInt16

Not supported

Date

System.DateTime

Visual Basic includes an intrinsic Date type, an alias for the framework’s System.DateTime type. C# does not include a parallel date/time type. Instead, you must use System.DateTime directly in C#.

For more information about the intrinsic data types, see their individual entries elsewhere in this chapter.

decimal Data Type

Visual Basic’s intrinsic Decimal data type is identical to C#’s decimal data type. Both types are aliases for .NET’s System.Decimal type. For decimal literals, C# uses an M or m suffix after the value; in Visual Basic, use D, d, or @ instead.

C#

decimal cost = 0m;  // or 0M

VISUAL BASIC

Dim cost As Decimal = 0@  ' or 0D or 0d

default Clause

See

switch Statement

default Operator

In C#, the default operator assigns a default value to a variable instance, most commonly for generic type instances.

C#

// ----- Somewhere within "class Flexible<T> { }",

//       in one of its methods.

T oneValue = default(T);

In Visual Basic, the Nothing literal accomplishes the same thing.

VISUAL BASIC

' ----- Somewhere within "Class Flexible(Of T)...

'       End Class", in one of its methods.

Dim oneValue As T = Nothing

Because Visual Basic assigns a default value to all variable instances automatically, this assignment isn’t strictly needed at declaration. But you can also use Nothing to reset the instance back to its default value later within the method’s logic.

When checking a generic instance for its default value, use the EqualityComparer(Of T) type’s Default.Equals method.

VISUAL BASIC

' ----- Assumes: Imports System.Collections.Generic

If (EqualityComparer(Of T).Default.Equals(

    oneValue, Nothing)) Then

delegate Statement

Visual Basic’s Delegate statement is equivalent to C#’s delegate statement.

C#

public delegate int PerformCalculation(int x, int y);

VISUAL BASIC

Public Delegate Function PerformCalculation(

    ByVal x As Integer, ByVal y As Integer) _

    As Integer

As with standard Visual Basic methods, delegates destined to return a value use the Function modifier; those that do not return a value (a void return in C#) use the Sub modifier instead.

Delegates support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

internal

Friend

new

Shadows

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

static

Shared

C# uses a variation of the delegate statement to establish inline event handlers and other anonymous methods.

C#

button1.Click += delegate(object o, EventArgs e) {

    /* Event code here. */ };

Visual Basic’s lambda statements provide this same functionality.

VISUAL BASIC

AddHandler Button1.Click, Sub(ByVal o As Object,

            ByVal e As EventArgs)

        ' ----- Event code here.

    End Sub

See Also

Anonymous Methods

Destructors

In C# classes, a destructor appears as a method with the same name as the class, prefixed with a tilde character (~).

C#

class Customer

{

    ~Customer()

    {

        // ----- Cleanup logic appears here.

    }

}

The C# compiler converts this code to the following more verbose equivalent.

C#

class Customer

{

    protected override void Finalize()

    {

        try

        {

            // ----- Cleanup logic appears here.

        }

        finally

        {

            // ----- This is called automatically.

            // base.Finalize();

        }

    }

}

This converted format closely parallels the version that should be used in Visual Basic classes to create destructors.

VISUAL BASIC

Class Customer

    Protected Overrides Sub Finalize()

        Try

            ' ----- Cleanup logic appears here.

        Finally

            MyBase.Finalize()

        End Try

    End Sub

End Class

In both languages, the garbage collector determines when to call the destructor.

Directives

See

Preprocessing Directives

do Statement

C#’s do statement loops while a condition is true, and is guaranteed to loop at least once, since the condition is not evaluated until the loop completes one iteration.

C#

do

{

    content = ProcessChunkOfContent(content);

} while (content.Length > 0);

In Visual Basic, the Do statement accomplishes the same thing when the condition appears at the bottom of the loop.

VISUAL BASIC

Do

    content = ProcessChunkOfContent(content)

Loop While content.Length > 0

A variation of this loop uses the Until clause instead of While.

VISUAL BASIC

Do

    content = ProcessChunkOfContent(content)

Loop Until content.Length = 0

In Visual Basic, parentheses surrounding the condition are optional. They are required in C#.

See Also

while Statement

double Data Type

Visual Basic’s intrinsic Double data type is identical to C#’s double data type. Both types are aliases for .NET’s System.Double type. For double literals, C# uses a D or d suffix after the value; in Visual Basic, use R, r, or # instead.

C#

double factor = 0d;  // or 0D

VISUAL BASIC

Dim factor As Double = 0#  ' or 0R or 0r

Dynamic Binding

See

dynamic Type

dynamic Type

C#’s dynamic type declaration expression enables dynamic binding, often called “late binding” in Visual Basic.

C#

dynamic basicValue = 20;

dynamic complexValue = new ExampleType();

// ----- This method call is not checked

//       at compile-time.

complexValue.ProcessData();

In Visual Basic, late-bound instances are created as Object, and must be defined in a source file or project that uses Option Strict Off.

VISUAL BASIC

' ----- At the top of the file.

Option Strict Off

' ----- Later, in method code.

Dim basicValue As Object = 20

Dim complexValue As Object = New ExampleType()

' ----- This method call is not checked

'       at compile-time.

complexValue.ProcessData()

In both languages, when assigning a value type to a dynamic variable, boxing and unboxing will occur as the value is used throughout your code.

else Clause

See

if Statement

Entry Point

See

main Method

enum Statement

Visual Basic’s Enum statement is equivalent to C#’s enum statement.

C#

enum DoorState

{

    Closed = 1,

    Ajar,

    Open

}

VISUAL BASIC

Enum DoorState

    Closed = 1

    Ajar

    Open

End Enum

Both languages default each enumeration member to zero (for the first item) or one more than the item that precedes it, unless overridden with a specific value, as was done with DoorState.Closed in the prior sample. C# separates members with commas, while VB uses line breaks.

Both Visual Basic and C# support enumerations based on the eight core integer types (byte, sbyte, short, ushort , int, uint, long, ulong, and their Visual Basic counterparts), with int (C#) and Integer (VB) used by default.

C#

enum DoorState : long

VISUAL BASIC

Enum DoorState As Long

C# enumerations can appear within namespaces, classes, or structures. In addition to these, Visual Basic also permits the nesting of enumerations within interfaces.

Enumerations support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

internal

Friend

new

Shadows

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

Both languages use a dotted notation when accessing enumeration members in code.

New with Visual Studio 2015

In 2015, C# added a new using static statement that, when paired with an enumeration, allows use of the enumeration’s members without specifying the enumeration name in code. Visual Basic allows this through its Imports statement.

C#

// ----- Before 2015.

DoorState frontDoor = DoorState.IsClosed;

// ----- Starting in 2015, at the top of the file.

using static DoorNamespace;

using static DoorNamespace.DoorState;

// ----- Later, within a method.

DoorState backDoor = IsClosed;

VISUAL BASIC

' ----- At the top of the file.

Imports DoorNamespace

Imports DoorNamespace.DoorState

' ----- Later, within a method.

Dim frontDoor As DoorState = DoorState.IsClosed

' ----- This will also work thanks to the Imports.

Dim backDoor As DoorState = IsClosed

Error Handling

See

throw Statement, try Statement

Event Handlers

In C#, the += event subscription operator links an object’s event to a compatible event handler. The -= event unsubscription operator later breaks the association.

C#

// ----- Define the instance.

public Button button1 = new Button();

// ----- Define the handler.

void button1_Click(object sender, EventArgs e)

{

    // ----- Event-handling code here.

}

// ----- Elsewhere...

button1.Click += button1_Click;

In Visual Basic, the AddHandler and RemoveHandler statements, when used in conjunction with the AddressOf operator, perform the same function as C#’s += and -= event operators.

VISUAL BASIC

' ----- Define the instance.

Public Button1 As New Button()

' ----- Define the handler.

Sub Button1_Click(ByVal sender As Object,

        ByVal e As EventArgs)

    ' ----- Event-handling code here.

End Sub

' ----- To connect the event.

AddHandler Button1.Click, AddressOf Button1_Click

' ----- To disconnect the event.

RemoveHandler Button1.Click, AddressOf Button1_Click

Visual Basic also has an alternate syntax that uses WithEvents on the object declaration, and exchanges AddHandler and RemoveHandler for the Handles clause on the event handler.

VISUAL BASIC

' ----- Define the instance.

Public WithEvents Button1 As New Button()

' ----- Define the handler.

Sub Button1_Click(ByVal sender As Object,

        ByVal e As EventArgs) Handles Button1.Click

End Sub

Events can also use lambda expressions as event handlers.

C#

Button1.Click += (sender, e) => { /* Code here */ };

VISUAL BASIC

AddHandler Button1.Click, Sub(sender, e)

        ' ----- Code here.

    End Sub

See Also

+= Event Subscription Operator, -= Event Unsubscription Operator, event Statement

event Modifier

See

Attributes

event Statement

As in C#, Visual Basic includes support for delegate-based event declaration. Its Event statement, when used in this way, closely parallels the functionality of C#’s event statement.

C#

public delegate void SampleEventHandler(

    object sender, SampleEventArgs e);

public event SampleEventHandler SampleEvent;

VISUAL BASIC

Public Delegate Sub SampleEventHandler(

    ByVal sender As Object,

    ByVal e As SampleEventArgs)

Public Event SampleEvent As SampleEventHandler

Visual Basic also supports a combined syntax, where the signature of the delegate is included in the event declaration.

VISUAL BASIC

Public Event SampleEvent(ByVal sender As Object,

    ByVal e As SampleEventArgs)

An enhanced version of C#’s event statement adds custom logic that runs whenever an event handler is added to or removed from the event being defined. The add and remove blocks define the event-adding and event-removing logic, respectively. Each block implies a “value” variable, an event handler instance of the delegate type for the event.

C#

// ----- Same delegate as above.

public event SampleEventHandler SampleEvent

{

    add { /* Code using "value" here. */ }

    remove { /* Code using "value" here. */ }

}

Visual Basic has a similar extended syntax that adds the Custom modifier. In addition to add (AddHandler) and remove (RemoveHandler) blocks, the VB syntax includes a third block named RaiseEvent that hosts logic called every time the event is raised. This block has no direct equivalent in C#.

VISUAL BASIC

' ----- Same delegate as above.

Public Custom Event SampleEvent As SampleEventHandler

    AddHandler(ByVal value As SampleEventHandler)

        ' ----- Custom "add" code here.

    End AddHandler

    RemoveHandler(ByVal value As SampleEventHandler)

        ' ----- Custom "remove" code here.

    End RemoveHandler

    RaiseEvent(ByVal sender As Object,

            ByVal e As SampleEventArgs)

        ' ----- Custom "raise" code here. The

        '       signature is the same as the

        '       delegate signature.

    End RaiseEvent

End Event

Events support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

abstract

Not supported

extern

Not supported

internal

Friend

new

Shadows

override

Not supported

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

sealed

Not supported

static

Shared

virtual

Not supported

Exceptions

See

throw Statement, try Statement

explicit Modifier

C#’s explicit modifier indicates that an overloaded conversion from one type to another must be performed explicitly, as the destination type may be too narrow for all the source type’s possible values.

C#

class BigType

{

    public static explicit operator SmallType(

        BigType source)

    {

        return new SmallType(source.GetCondensed());

    }

}

The equivalent Visual Basic overload uses the Narrowing modifier to express this same limiting conversion.

VISUAL BASIC

Class BigType

    Public Shared Narrowing Operator CType(

            ByVal source As BigType) As SmallType

        Return New SmallType(source.GetCondensed())

    End Operator

End Class

See Also

implicit Modifier, operator Statement

Extension Methods

In C#, extension methods appear in static classes, and use the this modifier to indicate the target type being extended.

C#

internal static class LocalExtensions

{

    public static string DigitsOnly(

        this string originalText)

    {

        // ----- Returns a string result.

    }

}

In Visual Basic, extension methods always appear in modules, which are akin to static classes in C#. The method must be decorated with the Extension attribute (from System.Runtime.CompilerServices). Although not marked with any special modifier, the first argument to the method is the target of the extension.

VISUAL BASIC

Imports System.Runtime.CompilerServices

Friend Module LocalExtensions

    <Extension> Public Function DigitsOnly(

            ByVal originalText As String) As String

        ' ----- Returns a string result.

    End Function

End Module

extern alias Statement

Visual Basic has no equivalent for C#’s extern alias statement. The closest alternative involves using Reflection to load and access members of an external assembly indirectly, a task that is beyond the scope of this book.

See Also

:: Namespace Alias Qualifier

extern Modifier

When used with the DllImport attribute (from System.Runtime.InteropServices), the extern modifier indicates a method sourced from an external file.

C#

[DllImport("avifil32.dll")]

private static extern void AVIFileInit();

Visual Basic includes support for this same functionality, but requires no specific modifier comparable to extern.

VISUAL BASIC

<DllImport("avifil32.dll")>

Private Shared Sub AVIFileInit()

End Sub

Beyond this attribute-centric declaration, Visual Basic’s Declare statement provides a more formal syntax for identifying methods from an external source.

VISUAL BASIC

Private Declare Sub InitAVI Lib "avifil32.dll" _

    Alias "AVIFileInit" ()

The Lib clause indicates the source file, while the optional Alias clause identifies the method name in the library for those times when you want to give it a different name within your code. Replace Sub with Function to import a method that returns data, and update the signature as needed.

Methods imported with the Declare statement are Public by default. Also, imported methods are assumed to work with ANSI character sets. To alter this default, follow the Default keyword with the Unicode, Auto, or (to make the default clear) Ansi keyword.

See Also

Methods

false Boolean Literal

Visual Basic’s False literal is identical to C#’s false literal.

Fields

Fields are variables declared within a class or structure (plus modules in VB), outside of any method. The syntax closely parallels that of local variable declaration. (See the “Variables” entry in this chapter for more declaration details.)

C#

// ----- Field declared with initializer.

private int MonitoredValue = 0;

VISUAL BASIC

' ----- Field declared with initializer.

Private MonitoredValue As Integer = 0

' ----- The "Dim" keyword is optional, but required

'       when no access modifier is used.

Dim AnotherValue As Integer

Access modifiers are optional in field declarations. When missing, the access level defaults to private in C# classes and structures. Within a Visual Basic Class or Module, fields are Private by default; they are Public by default when used in a Structure.

Fields support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

internal

Friend

new

Shadows

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

readonly

ReadOnly

static

Shared

volatile

Not supported

Not supported

WithEvents

See Also

[ ] Array Declaration, Access Modifiers, Identifiers, Initializers, new Operator, static Modifier, Variables

field Modifier

See

Attributes

finally Clause

See

try Statement

fixed Modifier

C#’s fixed modifier, used to create fixed-size buffers, is only valid in unsafe contexts. Because Visual Basic does not support unsafe code, there is no equivalent for this modifier in VB.

fixed Statement

C#’s fixed statement, used to prevent the .NET garbage collector from moving a block of memory, is valid only in unsafe contexts. Because Visual Basic does not support unsafe code, there is no equivalent for this statement in VB.

float Data Type

Visual Basic’s intrinsic Single data type is identical to C#’s float data type. Both types are aliases for .NET’s System.Single type. For single literals, C# uses an F or f suffix after the value; in Visual Basic, use F, f, or ! instead.

C#

float factor = 0f;  // or 0F

VISUAL BASIC

Dim factor As Single = 0!  ' or 0F or 0f

for Statement

For simple C# for loops that iterate from a starting number to an ending value, incrementing by a standard amount each time, Visual Basic’s For loop is an useful replacement.

C#

for (int counter = 0; counter < 10; counter++)

{

    // ----- Loops 10 times, from 0 to 9.

}

// ----- Outside-of-loop declaration of counter

//       is also valid.

int counter;

for (counter = 0; counter < 10; counter++)

{

}

VISUAL BASIC

For counter As Integer = 0 To 9

    ' ----- Loops 10 times, from 0 to 9, inclusive.

Next counter

' ----- Outside-of-loop declaration of counter

'       is also valid.

Dim counter As Integer

For counter = 0 To 9

Next counter

The loop counter in the VB statement can be integer (Byte, Short, Integer, or Long, or their signed and unsigned counterparts), a floating-point variable (Single, Double, or Decimal), or an enumeration. If you have another type that has overloaded the +, -, <=, >=, and CType operators, it can also be used. By default, the counter variable increases by one (1) each time through the loop. You can change this with the Step clause, followed by any positive or negative increment.

VISUAL BASIC

For counter As Decimal = 10@ To 1@ Step -2.5@

    ' ----- Values will be 10, 7.5, 5, and 2.5.

C#’s for statement permits even more complex looping scenarios, with support for multiple comma-delimited initializers (of the same data type) and iterators, and a condition section that supports any type of Boolean expression. None of these features are available in Visual Basic’s For loop. To support such loops, you will need to convert them to a Do statement, or manage these other variables in conjunction with a standard For loop. Use an Exit For or Exit Do statement to exit a loop early.

C#

string monthCode = "";

for (int month = 1; counter <= 12 &

        !monthCode.Contains("X"); counter++)

    monthCode += ProcessMonth(month);

VISUAL BASIC

' ----- Using a For statement.

Dim monthCode As String = ""

For month As Integer = 1 To 12

    monthCode &= ProcessMonth(month)

    If (monthCode.Contains("X")) Then Exit For

Next month

' ----- Using a Do statement.

Dim month As Integer = 1

Dim monthCode As String = ""

Do While (month <= 12) And

        (Not monthCode.Contains("X"))

    monthCode &= ProcessMonth(month)

    month += 1

Loop

In C#, you can create an infinite loop by leaving the condition portion (or all portions) blank.

C#

for (;;) { }

To do this in Visual Basic, use a Do statement instead.

VISUAL BASIC

Do

Loop

In both languages, you can alter the counter variable within the body of the loop. The starting, ending, and increment (step) values in a For loop, however, are evaluated only once, before the loop begins, and cannot be changed from within the loop.

foreach Statement

Visual Basic’s For Each statement is equivalent to C#’s foreach statement.

C#

foreach (DataRow scanRow in customerTable.Rows)

{

    // ----- Logic using scanRow variable.

}

VISUAL BASIC

For Each scanRow As DataRow In customerTable.Rows

    ' ----- Logic using scanRow variable.

Next scanRow

Visual Basic allows the iteration variable to be declared outside of the loop.

VISUAL BASIC

Dim scanRow As DataRow

For Each scanRow In customerTable.Rows

This is not permitted in C#; you must declare the loop variable type as part of the statement declaration. (The type can be var for implicitly typed iterators.)

from Query Expression Operator (LINQ)

Visual Basic’s From query expression operator is identical to C#’s from operator. Both languages allow the clause to appear multiple times within the query. Visual Basic also allows a single From clause to include multiple comma-delimited sources.

C#

// ----- Single source.

var result = from item in Employees

             select new {item.FullName, item.HireDate};

// ----- Multiple sources.

var result = from item in Employees

             from site in Divisions

             where item.Division == site.ID

             select new {Division = site.Name,

             item.FullName};

VISUAL BASIC

' ----- Single source.

Dim result = From item In Employees

             Select item.FullName, item.HireDate

' ----- Multiple comma-delimited sources.

Dim result = From item In Employees, site In Divisions

             Where item.Division = site.ID

             Select Division = site.Name, item.FullName

' ----- Multiple distinct sources.

Dim result = From item In Employees

             From site In Divisions

             Where item.Division = site.ID

             Select Division = site.Name, item.FullName

Visual Basic supports multiple From clauses when processing nested results.

VISUAL BASIC

Dim result = From customer In GetActiveCustomers()

             From order In customer.Orders

             Select order

Normally, the range variable is inferred from the collection type. To explicitly identify the range variable type, include an As clause.

VISUAL BASIC

Dim result = From item As Employee In AllEmployees

In C#, the from clause is required in all query expressions. In Visual Basic, the From clause is normally required. However, when building aggregate queries, the From clause is not required if the query expression begins with the Aggregate operator.

VISUAL BASIC

Dim averageSalary = Aggregate item In Employees

                    Into Average(item.Salary)

See Also

Query Expressions

Functions

See

Methods

Garbage Collection

See

Destructors

Generics

Both C# and Visual Basic support generics, also known as “constructed types.” One key difference is the syntax used to specify the type placeholders. In C#, these appear within angle brackets after the generic type name, while in Visual Basic, they appear in parentheses as part of an Of clause.

C#

// ----- As part of a generic declaration.

class SpecialList<T>

{

    private T InternalList;

}

// ----- As part of a generic instantiation.

SpecialList<int> trackNumbers = new SpecialList<int>();

VISUAL BASIC

' ----- As part of a generic declaration.

Class SpecialList(Of T)

    Private InternalList As T

End Class

' ----- As part of a generic instantiation.

Dim trackNumbers As New SpecialList(Of Integer)

Generic constructs can be applied to classes, structures, interfaces, methods, and delegates in both languages. Generic methods can appear within generic or non-generic types.

C#

static void ReverseItems<T>(ref T firstItem,

    ref T secondItem)

{

    T holdingArea = firstItem;

    firstItem = secondItem;

    secondItem = holdingArea;

}

VISUAL BASIC

Shared Sub ReverseItems(Of T)(ByRef firstItem As T,

        ByRef secondItem As T)

    Dim holdingArea As T = firstItem

    firstItem = secondItem

    secondItem = holdingArea

End Sub

In both C# and Visual Basic, the generic type parameter list can include type-specific modifiers that provide limits for each parameter. C#’s where clause, like VB’s As clause, lets you limit the specific types that can be used for a type parameter during instantiation. See the “where Clause” entry in this chapter for more information. When defining generic interfaces, optional modifiers specify the variance associated with each type parameter. By default, type parameters are invariant. The “out” modifier in each language specifies covariance, while “in” specifies contravariance.

C#

interface IVariant<TInvariant, out TCovariant,

    in TContravariant>

{

}

VISUAL BASIC

Interface IVariant(Of TInvariant, Out TCovariant,

    In TContravariant)

End Interface

See Also

where Clause

get Declaration

See

Properties

global Namespace Alias

When used to indicate the root of the namespace hierarchy, Visual Basic’s Global namespace alias is equivalent to C#’s global alias.

C#

// ----- Perhaps you defined a MyApp.System.Exception

//       class in your application's code. This makes

//       it clear that you want .NET's Exception class.

global::System.Exception theProblem;

VISUAL BASIC

Dim theProblem As Global.System.Exception

See Also

:: Namespace Alias Qualifier

goto Statement

For ordinary jumps to line labels, Visual Basic’s GoTo statement is identical to C#’s goto statement.

VISUAL BASIC

GoTo SkipProcessing

Within switch statements, C# allows the use of goto case and goto default to redirect processing to another block within the switch statement. This syntax is not supported in VB. Instead, add a line label to the target block, and use a standard GoTo statement to jump to the other code.

C#

switch (token)

{

    case ">":

        term += "greater than";

        break;

    case ">=":

        term += "greater than or ";

        goto case "=";

    case "=":

        term += "equal to";

        break;

}

VISUAL BASIC

Select Case token

    Case ">"

        term &= "greater than"

    Case ">="

        term &= "greater than or "

        GoTo EqualsTo

    Case "="

EqualsTo:

        term &= "equal to"

End Select

See Also

Labels

group Query Expression Operator (LINQ)

Visual Basic’s Group query expression operator parallels C#’s group operator. In C#, a single expression or range variable target is grouped by one or more grouping expressions. In Visual Basic, the target can be an expression, a range variable, a comma-delimited list of expressions, or missing altogether, which implies that all range variables or fields should be the target.

C#

// ----- Grouping of range variable.

var result = from item in Employees

             group item by item.Department;

// ----- Grouping of specific field.

var result = from item in Employees

             group item.FullName by item.Department;

// ----- Grouping of multiple fields.

var result = from item in Employees

             group new {item.FullName, item.HireDate}

             by item.Department;

VISUAL BASIC

' ----- Grouping of range variable.

Dim result = From item In Employees

             Group By item.Department Into Group

' ----- Grouping of specific field.

Dim result = From item In Employees

             Group item.FullName

             By item.Department Into Group

' ----- Grouping of multiple fields.

Dim result = From item In Employees

             Group item.FullName, item.HireDate

             By item.Department Into Group

To perform additional processing on the grouped results, the into clause (C#) identifies a temporary identifier used in subsequent clauses. In Visual Basic, the Into portion is required in all Group By expressions, as shown in the previous sample code block. Clauses that follow Group By refer to grouping elements directly, often without the alias prefix.

C#

var result = from item in Employees

             group item by item.Department into deptSets

             orderby deptSets.Key

             select deptSets;

VISUAL BASIC

Dim result = From item In Employees

             Group By item.Department Into deptSets = Group

             Order By Department

             Select deptSets

Visual Basic’s Into clause supports additional aggregate functions. This syntax is not supported directly in C#, but requires an additional select clause.

C#

var result = from item in Employees

             group item by item.Department into deptSets

             select new { DeptName = deptSets.Key,

                          DeptMembers = deptSets.Count() };

VISUAL BASIC

' ----- In this variation, the results will also include

'       subordinate "item" records, although C# version

'       will only include department name and count.

Dim result = From item In Employees

             Group By item.Department

             Into Group, Count()

See Also

Query Expressions

Identifiers

Both C# and Visual Basic use a common set of identifier naming rules, allowing for a mixture of letters, digits, and underscores, with some limitations, such as not starting an identifier with a digit.

Identifiers in C# are case-sensitive. Two variables named customerName and CustomerName in the same method would not conflict since the first letter is a different case. In Visual Basic, identifiers are case-insensitive. In VB, two identifiers are identical if they are the same when converted to all lower-case letters. It is possible to create an assembly in C# with two exposed type or member names that differ only by case. Such naming would cause problems when consumed by a Visual Basic project, although VB does have rules that attempt to identify the most accessible element when there is a conflict.

Visual Basic allows you to give the same (case-insensitive) name to a type and one of its members.

VISUAL BASIC

' ----- This is valid in Visual Basic.

Public Class ItemData

    Public ItemText As String

    Public ItemData As Long

End Class

C# does not allow this combination. You must not name a type member the same as its enclosing type in C#. If you create a Visual Basic assembly that has this shared naming of type and member, a C# project will not be able to access the member directly.

C# allows identifiers to include Unicode escape sequences in the form \Uhhhh, where hhhh is a 4- or 8-digit hex value. The hex code must still resolve to a character considered valid for identifiers, typically variations of the core alphanumeric characters.

C#

string p\00E8re = "French for 'father'";

MessageBox.Show(string.Format("{0} is {1}",

    nameof(p\00E8re), p\00E8re));

// ----- Displays: père is French for 'father'

Visual Basic does not include support for these sequences. You can use a Unicode character within an identifier name in VB, but it must be entered as a standard character within the code, and not as an escape sequence.

VISUAL BASIC

Dim père As String = "French for 'father'"

MessageBox.Show(String.Format("{0} is {1}",

    NameOf(père), père));

' ----- Displays: père is French for 'father'

Both languages allow you to create identifiers that conflict with reserved language keywords. To use such identifiers, prefix them with the @ symbol in C#, or surround them with square brackets in Visual Basic.

C#

long @for = 0L;

VISUAL BASIC

Dim [For] As Long = 0&

Microsoft recommends that identifier names be either Pascal-cased or camel-cased. In Pascal casing, every distinct word within the name has an initial capital, including the start of the identifier. Camel casing is similar, but the initial letter is lowercase.

C#

int PascalCaseExample;

int camelCaseExample;

As indicated in Visual Studio’s documentation, camel casing is recommended for parameter names, local variable names, and protected instance fields within types. All other identifiers, including line labels, should use Pascal casing.

if Statement

Visual Basic’s If statement closely parallels the if statement in C#.

C#

if (testDate < DateTime.Now)

    era = "Past";

else if (testDate == DateTime.Now)

    era = "Present";

else

    era = "Future";

VISUAL BASIC

If (testDate < Now) Then

    era = "Past"

ElseIf (testDate = Now) Then

    era = "Present"

Else

    era = "Future"

End If

Each condition in VB begins with If or ElseIf, and ends with Then before moving into the logic for that condition. The entire statement ends with End If. Visual Basic includes a condensed version of the statement that puts the Then and Else parts on a single logical line. (This syntax works in C# as well, but that’s due to the way that whitespace is used, and not because of the grammar of the if statement, as is the case in VB.)

VISUAL BASIC

' ----- Simple If with no Else component.

If problemOccurred Then ErrorField.Visible = True

' ----- Simple If with Else component.

If (IsValidZip(zipCode) = True) Then _

    city = GetZipCity(zipCode) Else city = "Unknown"

In this simple version of the statement, the End If closing token is not used. As shown in the second example, you may need to include a line continuation character (_) if the logical line breaks across more than one physical line.

As in C#, Visual Basic’s conditional statements can include any mix of expressions or logical operators, just as long as the result of each expression is a Boolean value. You must surround the condition in C# with a set of parentheses; these parentheses are optional in VB. Visual Basic supports any number of ElseIf clauses, and you can nest If statements, just like in C#.

implicit Modifier

C#’s implicit modifier indicates that an overloaded conversion from one type to another may be performed implicitly, as the destination type is wide enough for all the source type’s possible values.

C#

class SmallType

{

    public static implicit operator BigType(

        SmallType source)

    {

        return new BigType(source.GetValue());

    }

}

The equivalent Visual Basic overload uses the Widening modifier to express this same conversion.

VISUAL BASIC

Class SmallType

    Public Shared Widening Operator CType(

            ByVal source As SmallType) As BigType

        Return New BigType(source.GetValue())

    End Operator

End Class

See Also

explicit Modifier, operator Statement

in Modifier

See

Generics

Indexers

See

this Indexer Declaration

Inheritance

C# indicates a type’s base class using the : symbol.

C#

// ----- Dog derives from Animal, and

//       implements IDomesticate.

public class Dog : Animal, IDomesticate

In Visual Basic, use the Inherits statement on the first line within the class definition.

VISUAL BASIC

' ----- Dog derives from Animal, and

'       implements IDomesticate.

Public Class Dog

    Inherits Animal

    Implements IDomesticate

C# indicates both derived classes and implemented interfaces after the : symbol. In VB, these two relationships must be separated with the Inherits and Implements statements, as shown in the preceding sample.

See Also

: Base Declaration Indicator, base Constructor Declaration

Initializers

In C#, while you don’t need to provide initialization at the moment of declaration for fields and local variables, you must initialize these variables before they are used in code. Visual Basic automatically initializes all fields and local variables to their default values (typically Nothing or some variation of zero) when no other initialization is used. Neither language allows you to provide in-line initialization of instance fields in structures. These must be initialized within a constructor.

Basic initialization of variables and constants in both languages is done with an assignment.

C#

const decimal closeToPi = 3.2m;

int notInitialized;

int startingZero = 0;

string startingUnused = null;

string startingEmpty = "";

Customer readyToUse = null;

Customer fromExpression = GetCustomer(123);

VISUAL BASIC

Const closeToPi As Decimal = 3.2@

Dim notInitialized As Integer

Dim startingZero As Integer = 0

Dim startingUnused As String = Nothing

Dim startingEmpty As String = ""

Dim readyToUse As Customer = Nothing

Dim fromExpression As Customer = GetCustomer(123)

In both languages, object initializers let you set member fields and properties as part of instance declaration. The member values appear in a set of curly braces. In Visual Basic, this block appears as part of a With clause, and each member is prefixed with a period.

C#

// ----- Explicit type

Animal cat = new Animal {Age = 5, Name = "Fluffy"};

// ----- Implicit type

var kitten = new Animal {Age = 0, Name = "Kitty"};

// ----- With custom constructor

Employee boss = new Employee("John Smith")

    {Title = "President"};

VISUAL BASIC

' ----- Explicit type

Dim cat1 As New Animal With {.Age = 5, .Name = "Fluffy"}

Dim cat2 As Animal = New Animal With {.Age = 10,

    .Name = "Fang"}

' ----- Implicit type

Dim kitten = New Animal With {.Age = 0, .Name = "Kitty"}

' ----- With custom constructor

Dim boss As New Employee("John Smith") With _

    {.Title = "President"}

Both C# and Visual Basic can initialize arrays and collections as part of instance declaration. Notice the From clause used when initializing a collection in Visual Basic.

C#

// ----- Array. In the explicitSize declaration, "4"

//       refers to the size, not the upper bound.

int[] implicitSize = new int[] {2, 3, 5, 7, 11};

int[] explicitSize = new int[4] {13, 17, 19, 23};

int[] simpler = {29, 31, 37};

int[,] multiDimension = {{1, 2}, {3, 4}};

int[][] jagged = {new int[] {1, 2, 3},

                  new int[] {4, 5, 6, 7, 8}};

// ----- Collection

List<int> basicList = new List<int> {1, 2, 3, 4, 5};

var dayInfo = new Dictionary<int, string>

    {{0, "Sunday"}, {1, "Monday"}};

VISUAL BASIC

' ----- Array. In the explicitSize declaration, "3"

'       refers to the upper bound, not the size.

Dim implicitSize() As Integer = {2, 3, 5, 7, 11}

Dim explicitSize() As Integer =

    New Integer(3) {13, 17, 19, 23}

Dim simpler() As Integer = {29, 31, 37}

Dim multiDimension(,) As Integer = {{1, 2}, {3, 4}}

Dim jagged()() As Integer = New Integer(1)() _

    {New Integer() {1, 2, 3},

    New Integer() {4, 5, 6, 7, 8}}

' ----- Collection

Dim basicList As New List(Of Integer) From {1, 2, 3, 4, 5}

Dim dayInfo = New Dictionary(Of Integer, String) _

    From {{0, "Sunday"}, {1, "Monday"}}

Here is a more involved example that combines collection and object initializers.

C#

List<Cat> moreCats = new List<Cat>

{

    new Cat() {Name = "Furrytail", Age = 5},

    new Cat() {Name = "Peaches", Age = 4}

};

VISUAL BASIC

Dim moreCats As New List(Of Cat) From

{

    New Cat() With {.Name = "Furrytail", .Age = 5},

    New Cat() With {.Name = "Peaches", .Age = 4}

}

Collection initializers can be used as expressions, wherever a collection or array is expected.

C#

int result = CondenseArray(new int[] {1, 2, 3});

VISUAL BASIC

Dim result As Integer =

    CondenseArray(New Integer() {1, 2, 3})

Initialization of anonymous types in both languages follows the syntax of standard initialization.

C#

var pet = new {Age = 3, Name = "Rover"};

VISUAL BASIC

Dim pet = New With {.Age = 3, .Name = "Rover"}

When working with generics, C#’s default operator lets you assign the default value of a type to a variable. In Visual Basic, the Nothing literal provides the same functionality.

C#

class Special<T>

{

    public T watchValue = default(T);

}

VISUAL BASIC

Class Special(Of T)

    Public watchValue As T = Nothing

End Class

New with Visual Studio 2015

Originally, C# did not allow automatic properties to be initialized as part of the declaration itself. In 2015, the language gained this functionality for both read-only and read-write properties. Visual Basic already included such initialization features for read-write auto-properties, but initialization of read-only automatic properties came about in that same 2015 release.

C#

// ----- Read-write property.

public string CoreName { get; set; } = "Unknown";

// ----- Read-only property.

public string CoreName { get; } = "Unknown";

VISUAL BASIC

' ----- Read-write property.

Public Property CoreName As String = "Unknown"

' ----- Read-only property.

Public ReadOnly Property CoreName As String = "Unknown"

New with Visual Studio 2015

Starting in 2015, C# has a new syntax for initializing indexed collections.

C#

Dictionary<int, string> currencyFaces =

    new Dictionary<int, string> {

        [1] = "Washington",

        [5] = "Lincoln",

        [10] = "Hamilton"

    };

This new syntax is not available in Visual Basic. Instead, you must add items through the type’s standard item-adding features, such as through an Add method.

int Data Type

Visual Basic’s intrinsic Integer data type is identical to C#’s int data type. Both types are aliases for .NET’s System.Int32 type. For integer literals, Visual Basic uses an I, I , or % suffix after the value; C# does not include such a suffix.

C#

int counter = 0;

VISUAL BASIC

Dim counter As Integer = 0%  ' or 0I or 0i

interface Statement

Visual Basic’s Interface statement is equivalent to C#’s interface statement. When declaring an interface that derives from one or more interfaces, VB’s Inherits clause lists those interfaces, appearing as the first line within the Interface statement.

C#

interface ISomethingNew : ISomethingOld

{

    // ----- Members appear here.

}

VISUAL BASIC

Interface ISomethingNew

    Implements ISomethingOld

    ' ----- Members appear here.

End Interface

Interfaces in C# can include methods, properties, events, and indexers. Visual Basic supports all these members, and can also include subordinate interfaces, classes, and structures, none of which can be included in C# interfaces.

C#

interface IOptions

{

    // ----- Methods with and without return

    int MethodWithData(string incoming);

    void WorkOnlyMethod();

    // ----- Property and Indexer

    string Name {get; set;}

    string this[int index] {get;}

    // ----- Event (with delegate defined elsewhere)

    event DelegateSignature EventName;

}

VISUAL BASIC

Interface IOptions

    ' ----- Methods with and without return

    Function MethodWithData(

        ByVal incoming As String) As Integer

    Sub WorkOnlyMethod()

    ' ----- Property and Indexer

    Property Name() As String

    Default ReadOnly Property Item(

        ByVal index As Integer) As String

    ' ----- Event (with and without defined delegate)

    Event EventFromDelegate As DelegateSignature

    Event EventDefinedInline(ByVal source As Object)

    ' ----- Class

    Class SubordinateClass

        ' ----- Members here

    End Class

    ' ----- Structure

    Structure SubordinateStructure

        ' ----- Members here

    End Structure

    ' ----- Interface

    Interface ISubordinate

        ' ----- Members here

    End Interface

End Interface

Interfaces support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

internal

Friend

new

Shadows

partial

Partial (starting in 2015)

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

Interfaces in C# are internal by default, just as interfaces in Visual Basic are Friend by default. In both languages, all members are public by definition.

During implementation of an interface, Visual Basic uses the Implements modifier, both on the type and explicitly on each implementing member.

C#

class Employee : IPerson

{

    public string IPerson.Name

    {

         // ----- Implementation here.

    }

}

VISUAL BASIC

Class Employee

    Implements IPerson

    Public Property Name As String Implements IPerson.Name

         ' ----- Implementation here.

    End Property

End Class

Because the Implements clause on the member includes the name of the interface member, the name of the class member implementing the item does not have to be the same in Visual Basic. In C#, the implementing member name is always the same as the interface member name being implemented.

internal Access Modifier

Visual Basic’s Friend access modifier is equivalent to C#’s internal access modifier.

See Also

Access Modifiers

is Comparison Operator

Both C#’s is operator and Visual Basic’s TypeOf...Is operator return true if the object being tested is of a specified type, or can be implicitly converted to that type.

C#

if (personVariable is Customer)

VISUAL BASIC

If (TypeOf personVariable Is Customer) Then

New with Visual Studio 2015

Beginning with its 2015 release, Visual Basic added a new TypeOf...IsNot operator that returns the Boolean opposite of the TypeOf...Is operator.

Visual Basic includes an Is operator (without TypeOf) that compares object instances. It is not the same as either TypeOf...Is or C#’s is operator.

Iterators

In C#, iterators are functions or properties that include the yield return statement. In Visual Basic, iterators are also built from functions or properties, include the Yield statement, and are declared using the Iterator modifier.

C#

public IEnumerable<int> FirstFivePrimes()

{

    yield return 2;

    yield return 3;

    yield return 5;

    yield return 7;

    yield return 11;

}

VISUAL BASIC

Public Iterator Function FirstFivePrimes() As _

        IEnumerable(Of Integer)

    Yield 2

    Yield 3

    Yield 5

    Yield 7

    Yield 11

End Function

When implemented as a read-only property, Visual Basic employs both the Iterator and ReadOnly modifiers on the property declaration.

C#

public IEnumerable<int> EvensOnly(int maximum)

{

    get

    {

        for (int value = 2; value <= maximum; value++)

            yield return value;

    }

}

VISUAL BASIC

Public ReadOnly Iterator Property EvensOnly(

        ByVal maximum As Integer) As _

        IEnumerable(Of Integer)

    Get

        For value As Integer = 2 To maximum

            Yield value

        Next value

    End Get

End Property

Visual Basic allows the Iterator modifier to be used with an anonymous method. This variation is not supported in C#.

join Query Expression Operator (LINQ)

Visual Basic’s Join query expression operator is the same as the join operator in C#.

C#

var result = from item in Employees

             join dept in Departments

             on item.Department equals dept.ID

             select new {item.FullName, dept.DeptName};

VISUAL BASIC

Dim result = From item In Employees

             Join dept In Departments

             On item.Department Equals dept.ID

             Select item.FullName, dept.DeptName

As with C#, Visual Basic also supports group joins using the Group Join syntax. C# doesn’t include an equivalent “group” keyword, but its into clause parallels the Into clause used in the VB version.

C#

var result = from dept in Departments

             join emp in Employees

             on dept.ID equals emp.Department into empSets

             select new {dept.DeptName,

             RecentHires = empSets};

VISUAL BASIC

Dim result = From dept In Departments

             Group Join emp In Employees

             On dept.ID Equals emp.Department Into Group

             Select dept.DeptName, RecentHires = Group

In both languages, you can use multiple “from” and “where” clauses to perform joins between different range sources. See the “from Query Expression Operator” entry in this chapter for an example that uses this syntax.

See Also

Query Expressions

Labels

Both C# and Visual Basic support line labels within methods. In both languages, a colon (:) follows the label.

C#

StartOver:

    // ----- Later...

    goto StartOver;

VISUAL BASIC

StartOver:

    ' ----- Later...

    GoTo StartOver

Line labels are case-sensitive in C#; you can include two identically named labels in the same method as long as they vary by case. In Visual Basic, labels are case-insensitive. Do not use two labels of the same name, even if the case varies.

Visual Basic allows labels to be wholly numeric. This is not supported in C#.

VISUAL BASIC

100:

    ' ----- Some code here.

See Also

goto Statement

Lambda Expressions

See

=> Lambda Operator

Late Binding

See

dynamic Type

let Query Expression Operator (LINQ)

Visual Basic’s Let query expression operator is identical to C#’s let operator.

C#

var result = from oneEmployee in Employees

             let annualSalary =

             oneEmployee.WeeklySalary * 52

             where annualSalary >= 50000

             select new {oneEmployee.FullName,

             annualSalary};

VISUAL BASIC

Dim result = From oneEmployee in Employees

             Let annualSalary =

             oneEmployee.WeeklySalary * 52

             Where annualSalary >= 50000

             Select oneEmployee.FullName, annualSalary

See Also

Query Expressions

Lifetime and Scope

With one significant difference within method code, C# and Visual Basic generally follow the same lifetime and scoping rules for variables.

Lifetime

Lifetime indicates how long the value stored within a variable remains available. Both languages mostly follow the same rules for managing variable lifetime. static (C#) and Shared (VB) fields declared outside of methods have application lifetime, as do fields that appear within Visual Basic Module statements. Non-static and non-shared type-level fields have lifetimes that last as long as the instance does. Local Static variables in Visual Basic methods have application- or instance-lifetime, depending on whether the containing method is Shared or not, respectively. C# does not support local static variables.

The key difference between the languages appears when using non-static local variables. In Visual Basic, all local non-static variables, whether declared inside or outside of a given block, have procedure-lifetime. If you declare a variable within an If statement block, its value will remain throughout the entire procedure, although scoping rules limit access to the variable to just that block. This means that if you reenter the block, the variable may retain the value it had the last time you passed through that block. Because of this, you should always initialize variables defined within a block.

In C#, variables have block-level lifetimes. If you declare a variable within an if statement block, its lifetime ends upon exiting that block.

Scope

Scope refers to which parts of your source code have access to a specific identifier. C# and Visual Basic follow the same scoping rules for type-level, procedure-level, and block-level variables.

LINQ

See

Query Expressions

Literals

C# and Visual Basic both support a wide range of value type literals, although there are some significant feature differences between the languages.

Unicode Sequences

String and character literals in C# support Unicode escape sequences, prefixed with the \U or \u escape code.

C#

// ----- \u00a3 is the British Pound symbol.

char currencySymbol = '\u00a3';

Visual Basic does not support such sequences. You must either embed the character itself within the literal, or use VB’s ChrW function to obtain a character representation of the Unicode value.

VISUAL BASIC

' ----- Embed the symbol directly.

Dim currencySymbol As Char = "£"c

' ----- Use the ChrW function.

Dim currencySymbol As Char = ChrW(&H00A3)

C#’s \x variable-length hex-character escape sequence is also not supported in Visual Basic.

Character and String Literals

C# supports two types of string literals: standard literals with support for embedded escape sequences; and verbatim string literals, prefixed with the @ symbol. Visual Basic strings are identical to C#’s verbatim string literals, including the method of embedding double-quote symbols.

C#

string notice = @"This is ""verbatim"" text.";

VISUAL BASIC

Dim notice As String = "This is ""verbatim"" text."

C#’s standard string literals have no direct equivalent in Visual Basic. To simulate C#’s escape sequences, you must concatenate variations of these special characters into your target literal. VB includes some useful intrinsic literals for these symbols (found inMicrosoft.VisualBasic.Constants), or you can use those provided by the .NET Base Class Libraries (such as System.Environment.NewLine). You can also use Visual Basic’s Chr or ChrW functions to return a character based on its ASCII or Unicode numeric value, respectively.

C#

string endOfLine = "\r\n";

VISUAL BASIC

Dim endOfLine As String = vbCrLf

The following table lists the VB intrinsic literals that you can use in place of C#’s escape sequences.

Character

Hex

C#

Visual Basic

Alert

0x07

\a

Chr(7)

Backslash

0x5c

\\

\ within text

Backspace

0x08

\b

vbBack

Carriage Return

0x0d

\r

vbCr

Double Quote

0x22

\"

"" within text

Form Feed

0x0c

\f

vbFormFeed

Horizontal Tab

0x09

\t

vbTab

Line Feed

0x0a

\n

vbLf

MS-DOS Line Ending

0x0d,0x0a

\r\n

vbCrLf

Null Character

0x00

\0

vbNullChar

Single Quote

0x27

\'

' within text

Vertical Tab

0x0b

\v

vbVerticalTab

New with Visual Studio 2015

C# verbatim strings can break across physical line boundaries, resulting in an embedded line break in the literal string. Beginning in 2015, Visual Basic supports this as well.

C#

string multiLine = @"First Line

Second Line";

VISUAL BASIC

' ----- 2015 and later only.

Dim multiLine As String = "First Line

Second Line"

Visual Basic releases before 2015 do not allow an open string to cross a physical line. Concatenate a line ending into the string as needed.

VISUAL BASIC

Dim multiLine As String = "First Line" & vbCrLf &

    "Second Line"

Character literals in C# appear in single quotes. In VB, use double-quotes, followed by the c suffix.

C#

char oneDigit = '0';

VISUAL BASIC

Dim oneDigit As Char = "0"c

New with Visual Studio 2015

In 2015, both C# and Visual Basic added string interpolation, a method of generating formatted strings using string literals. Both languages share an identical syntax for such strings, prefixing them with a $ symbol, and using curly braces to contain the interpolated sections.

Integer Literals

In C#, a plain integer literal will be typed as int if the value fits in that type. If not, it is coerced into the smallest of uint, long, or ulong. In Visual Basic, integer literals are Integer by default, or if too large for that type, then Long.

Each language supports a set of suffixes that force an integer literal to become a specific type. The following sample includes a long integer value in each language.

C#

PassALongValue(123L);

VISUAL BASIC

PassALongValue(123&)

The following table lists the suffixes for each integer type. Each suffix can be uppercase, lowercase, or for suffixes with more than one character, a mix of casing.

Data Type

C# Suffix

Visual Basic Suffix

Short

No suffix

S

Unsigned Short

No suffix

US

Integer

No suffix

% or I

Unsigned Integer

U

UI

Long

L

& or L

Unsigned Long

UL or LU

UL

Floating-Point Literals

In both languages, floating-point literals are double/Double by default. You can also alter this default by appending a type suffix to the literal value. The following table lists the suffixes for each floating-point type. Each suffix can be uppercase or lowercase.

Data Type

C# Suffix

Visual Basic Suffix

Single

F

! or F

Double

D

# or R

Decimal

M

@ or D

Both Visual Basic and C# allow numeric literals in exponential format (scientific notation). Either the base or the exponent can include a unary + or – sign, and an optional type character can appear as well.

C#

bigValue = 9.24E22D;  // double

VISUAL BASIC

bigValue = 9.24E+22#   ' Double

Boolean Literals

Visual Basic’s True and False Boolean literals are exact replacements for C#’s true and false literals. See the “bool Data Type” entry in this chapter for information on differences between the languages when converting a true value to an integer.

Hexadecimal and Octal Literals

C# supports hexadecimal literals using the 0x prefix. Visual Basic offers both hexadecimal and octal literals via the &H and &O prefixes.

C#

decimal25 = 0x19;

VISUAL BASIC

decimal25 = &H19

decimal25 = &O31

The various type suffixes, listed earlier in this entry, can follow the hexadecimal and octal literals to force the expression to a specific type.

Date Literals

New with Visual Studio 2015

Visual Basic includes intrinsic support for date and time literals. The text of the date or time appears between a set of # symbols. Before the 2015 update of Visual Basic, all date literals used a format common in the United States. With the Roslyn update, these literals also support a standard ISO date format.

VISUAL BASIC

Dim justDate As Date = #12/31/1999#

Dim justTime As Date = #12:34:56PM#

Dim bothParts As Date = #12/31/1999 12:34:56PM#

' ----- New international format.

Dim worldwideDate As Date = #1999-12-31#

The null Literal

C# includes a null literal that indicates an undefined reference type. In Visual Basic, the Nothing literal does the same for reference types. For value types, Nothing acts like C#’s default operator, returning the default value.

Local Variables

See

Variables

lock Statement

Visual Basic’s SyncLock statement is equivalent to C#’s lock statement.

C#

class VitalMethods

{

    private object HoldLock = new object();

    public void PerformVitalAction()

    {

        lock (HoldLock)

        {

            // ----- Protected code here.

        }

    }

}

VISUAL BASIC

Class VitalMethods

    Private HoldLock As New Object

    Public Sub PerformVitalAction()

        SyncLock HoldLock

            ' ----- Protected code here.

        End SyncLock

    End Sub

End Class

Logical Operators

See

Operators

long Data Type

Visual Basic’s intrinsic Long data type is identical to C#’s long data type. Both types are aliases for .NET’s System.Int64 type. For long literals, C# uses an L or l suffix after the value; in Visual Basic, use L, l, or & instead.

C#

long distance = 0L;  // or 0l

VISUAL BASIC

Dim distance As Long = 0&  ' or 0L or 0l

Main Method

In both C# and Visual Basic, an application uses a Main method as the program’s entry point. These routines are always static (C#) or Shared (VB, although the Shared modifier is assumed if the method appears in a Module), return either no result (void or Sub) or an integer, and can be defined with one argument, an array of command line argument strings. While C# allows these methods to be private, this is not allowed in Visual Basic.

C#

// ----- Plain version with no return or arguments.

static void Main()

{

}

// ----- Version with both a return code and arguments.

static int Main(string[] args)

{

}

VISUAL BASIC

' ----- Plain version with no return or arguments.

Shared Friend Sub Main()

End Sub

' ----- Version with both a return code and arguments.

Shared Friend Function Main(

    ByVal cmdArgs() As String) As Integer

End Function

In Visual Basic Windows Forms applications, a form can be defined as the startup object. Although you can include your own custom Main method within the form, the compiler will provide the method behind the scenes if one does not exist. In C# Windows Forms applications, the Main method is decorated with the STAThread attribute.

C#

[STAThread] static void Main()

The Visual Basic compiler attaches this attribute automatically in Windows Forms applications, so you don’t need to provide it as an attribute in code.

In a Windows Forms application, the Main method can be used to run custom code before displaying the initial form. This structure is standard in C# applications, although it is less common in VB, since that language provides other features that simplify the application startup process.

C#

static void Main()

{

    Application.Run(new Form1());

}

VISUAL BASIC

Shared Friend Sub Main()

    Application.Run(New Form1())

End Sub

An application normally exits when it reaches the end of the Main method. A program can be made to exit early by using one of the following features, sorted from most polite to most abrupt.

·        Calling System.Windows.Forms.Application.Exit()

·        Calling System.Environment.Exit(exitCode)

·        Using Visual Basic’s End statement

Visual Basic includes its Visual Basic Application Model, activated using the Enable Application Framework field in the Project Properties. When activated, the model enables features that provide for a more structured startup process, plus support for application-wide unhandled error monitoring. For more information on these features, read the Visual Studio documentation. You can also read the following entries in Chapter 3 of this book:

·        MinimumSplashScreenDisplayTime Property

·        NetworkAvailabilityChanged Event (My.Application)

·        SplashScreen Property

·        Startup Event

·        StartupNextInstance Event

·        UnhandledException Event

method Modifier

See

Attributes

Methods

Visual Basic’s Sub statement is equivalent to C# methods that have a void return value.

C#

public void LogError(string errorText)

{

    // ----- May optionally include this statement:

    return;

}

VISUAL BASIC

Public Sub LogError(ByVal errorText As String)

    ' ----- May optionally include this statement:

    Return

End Sub

The Sub keyword replaces void before the method name. In both languages, any parameter definitions appear in parentheses. The statement ends with VB’s End Sub clause.

In a similar way, the Function statement in Visual Basic parallels methods in C# that return anything other than void. The syntax is similar to that of the Sub statement, but with the keyword Function used instead of Sub. An As clause with the return type follows the parameter list.

C#

public bool ParseTimeText(string timeText,

    ref int hours, ref int minutes)

{

    // ----- Core logic, then...

    return success;

}

VISUAL BASIC

Public Function ParseTimeText(ByVal timeText As String,

        ByRef hours As Integer, ByRef minutes As Integer) _

        As Boolean

    ' ----- Core logic, then...

    Return success

End Function

When performing an explicit implementation of an interface member in C#, the name of the method is prefixed with the name of the interface.

C#

public void IVocal.Speak(string textToSpeak)

{

Visual Basic uses the Implements clause to indicate which interface member is being implemented explicitly by the method.

VISUAL BASIC

Public Sub Speak(ByVal textToSpeak As String) _

    Implements IVocal.Speak

When used to implement an event handler on an object defined with VB’s WithEvents modifier, the Handles clause identifies the source instance and event.

VISUAL BASIC

Public Sub Button1_Click(ByVal sender As Object,

    ByVal e As EventArgs) Handles Button1.Click

Methods support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

abstract

MustOverride

async

Async

extern

Not supported

internal

Friend

new

Shadows

override

Overrides

partial

Partial

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

sealed

NotOverridable Overrides, or NotOverridable in base class

static

Shared

virtual

Overridable

Not supported

Iterator

Not supported

Overloads

When defined without an access modifier, methods are private by default in C# classes and structures. In Visual Basic, all methods are Public by default.

When calling methods that include ref or out modifiers, C# requires that the associated argument in the calling code include those modifiers as well.

C#

success = ParseTimeText(timeText, ref hours, ref minutes);

Visual Basic does not require the use of any modifiers in the calling code. When calling methods that include no parameters, Visual Basic also does not require that the calling method follow the method name with an empty set of parentheses, although C# requires this, and VB recommends the practice.

New with Visual Studio 2015

In 2015, C# added the ability to define methods using lambda expressions.

C#

public Position Move(int xOffset, int yOffset) =>

    new Position(CurrentX + xOffset, CurrentY + yOffset);

Visual Basic does not yet support the creation of methods using lambdas.

See Also

, Punctuator, Arguments and Parameters, Access Modifiers, Event Handlers, Identifiers, Named Arguments

module Modifier

See

Attributes

nameof Operator

New with Visual Studio 2015

Visual Basic’s NameOf operator is identical to C#’s nameof operator.

C#

string variableName = nameof(customerName);

VISUAL BASIC

Dim variableName As String = NameOf(customerName)

namespace Statement

Visual Basic includes a Namespace statement that is functionally equivalent to C#’s namespace statement. Both languages support nesting of namespaces, either with individual namespaces at each level, or through a dotted-name syntax.

C#

namespace Level1

{

    namespace Level2.Level3

    {

    }

}

VISUAL BASIC

Namespace Level1

    Namespace Level2.Level3

    End Namespace

End Namespace

Within the Project Properties, C# includes support for a project’s Default Namespace, which Visual Studio uses for the surrounding namespace statement when adding new source code files to a project. Visual Basic includes a Root Namespace option in its Project Properties that indicates the top-most namespace for all source code files in the project, even in the absence of a distinct Namespace statement. If you include a Namespace statement in a file, that block is subordinate to the Root Namespace. To use a namespace outside of that default, you must make use of Visual Basic’s Global namespace alias.

VISUAL BASIC

' ----- Assume Root Namespace is "WindowsApp".

'       Classes here appear in that namespace.

Namespace UtilityCode

    ' ----- Classes here appear in the

    '       "WindowsApp.UtilityCode" namespace.

End Namespace

Namespace Global.SecondRoot

    ' ----- Classes here appear in "SecondRoot"

    '       instead of "WindowsApp".

End Namespace

See Also

:: Namespace Alias Qualifier, global Namespace Alias

new Constructor Declaration

See

Constructors

new Modifier

Visual Basic’s Shadows modifier hides a base member of the same name from being expressed in the derived class, just like C#’s new modifier.

C#

class DerivedClass : BaseClass

{

    // ----- Hides whatever BaseClass.BaseElement was.

    new public void BaseElement()

    {

    }

}

VISUAL BASIC

Class DerivedClass

    Inherits BaseClass

    ' ----- Hides whatever BaseClass.BaseElement was.

    Public Shadows Sub BaseElement()

    End Sub

End Class

In C#, the new modifier is optional; hiding of base elements occurs automatically as part of the declaration. In Visual Basic, the Shadows keyword is required to enable hiding.

new Operator

Visual Basic’s New operator is functionally equivalent to C#’s new operator when used to create new type instances. In both languages, the name of the type being instantiated and any parentheses-enclosed constructor arguments follow the operator.

C#

// ----- Examples with default and custom constructor.

Employee oneManager = new Employee();

Employee namedManager = new Employee("Jones");

VISUAL BASIC

' ----- Examples with default and custom constructor.

Dim oneManager As Employee = New Employee

Dim namedManager As Employee = New Employee("Jones")

As shown in the previous example, parentheses are required after the type name being instantiated only when constructor arguments are present. Visual Basic also supports a compressed format that combines the type identification and assignment of a new instance.

VISUAL BASIC

Dim oneManager As New Employee

As in C#, instance creation using the New operator can appear within expressions.

C#

authenticated = (new PasswordDialog()).PromptUser();

VISUAL BASIC

authenticated = (New PasswordDialog).PromptUser()

Anonymous types in C# use the new operator followed by a list of properties in curly braces.

C#

var namedAndNumbered = new { ID = 5, Name = "test" };

Visual Basic employs a similar syntax, with the inclusion of the With keyword. Notice that each property is prefixed with a period.

VISUAL BASIC

Dim namedAndNumbered = New With { .ID = 5, .Name = "test" }

VB also allows you to specify which anonymous type properties are “key” properties, those that can be used for equivalence testing between two instances.

VISUAL BASIC

Dim numberedByID = New With { Key .ID = 5, .Name = "test" }

See Also

Initializers

null Literal

C#’s null literal is a null reference for reference types and nullable value types.

C#

Employee oneManager = null;  // No instance

int? optionalNumber = null;  // No value

(When working with “null” values in database interactions, use System.DbNull instead of null.) In Visual Basic, the Nothing literal serves a similar purpose.

VISUAL BASIC

Dim oneManager As Employee = Nothing      ' No instance

Dim optionalNumber As Integer? = Nothing  ' No value

However, Nothing can also be assigned to a standard (non-nullable) value type, in which case it functions much like C#’s default operator, assigning the default value to the variable.

VISUAL BASIC

Dim requiredNumber As Integer = Nothing  ' Set to zero

Assigning null to a non-nullable value type in this manner in C# is invalid.

C#

// ----- This will not compile.

int requiredNumber = null;

// ----- Use this valid syntax instead.

int requiredNumber = default(int);

When comparing variables or expressions to null in C#, use the == and != comparison operators.

C#

if (customerRecord == null)

You cannot use the equivalent comparison operators (= and <>) in Visual Basic to check for Nothing. Instead, use VB’s Is and IsNot operators to compare expressions with Nothing .

VISUAL BASIC

' ----- Check for the absence of an instance.

If (customerRecord Is Nothing) Then

' ----- Check for the presence of an instance.

If (customerRecord IsNot Nothing) Then

Visual Basic propagates or discards Nothing in ways that are somewhat different from how C# uses null. This is both for reasons of backward compatibility in VB, and also because of Nothing’s dual nature as a null reference and a default value type. Compare the following examples to see just one difference.

C#

// ----- result will be set to "".

string result = (5 + null).ToString();

VISUAL BASIC

' ----- result will be set to "5".

Dim result As String = (5 + Nothing).ToString()

Visual Basic treats empty strings and Nothing as equivalent; C# distinguishes between null and empty strings.

C#

// ----- result will be set to "Not Empty".

string testValue = null;

if (testValue == "")

    result = "Empty";

else

    result = "Not Empty";

VISUAL BASIC

' ----- result will be set to "Empty".

Dim testValue As String = Nothing

If (testValue = "") Then

    result = "Empty"

Else

    result = "Not Empty"

End If

To test a VB string to see if it is unassigned, use Is Nothing instead.

VISUAL BASIC

If (testValue Is Nothing) Then

See Also

default Operator

Nullable Types

Both C# and Visual Basic use the ? symbol after a value type name to indicate a nullable value type.

C#

int? optionalNumber = null;

VISUAL BASIC

Dim optionalNumber As Integer? = Nothing

' ----- This is also a valid syntax.

Dim optionalNumber? As Integer = Nothing

In C#, it is valid to compare a nullable variable to null.

C#

if (optionalNumber == null)

In Visual Basic, you cannot directly compare the instance to Nothing in this way. Instead, use the Is or IsNot operators, or use the variable’s HasValue method.

VISUAL BASIC

' ----- This will work instead of = or <>.

If (optionalNumber Is Nothing) Then

' ----- This will also work in both languages.

If (optionalNumber.HasValue() = False) Then

In both languages, the nullable syntax is an alias for Nullable<T> (in C#) or Nullable(Of T) (in Visual Basic).

object Data Type

Visual Basic’s intrinsic Object data type is identical to C#’s object data type. Both types are aliases for .NET’s System.Object type.

C#

object result = null;

VISUAL BASIC

Dim result As Object = Nothing

Object Initializers

See

Initializers

Operator Overloading

See

operator Statement

operator Statement

Visual Basic’s Operator statement is equivalent to C#’s operator statement. In both languages, the “operator” keyword is followed by the specific operator symbol being overloaded, and the operands appear as parameters in the method-style definition.

C#

public static Team operator +(Team op1, Player op2)

{

    // ----- Logic to add player to team, then...

    return updatedTeam;

}

VISUAL BASIC

Public Shared Operator +(ByVal op1 As Team,

        ByVal op2 As Player) As Team

    ' ----- Logic to add player to team, then...

    Return updatedTeam

End Operator

The overload must be declared as public static in C#, and the equivalent Public Shared in Visual Basic. VB also allows the Overloads modifier to appear between Public and Shared, but it has no impact on the logic of the overload. In both languages, for unary operators, the parameter list will include only one parameter.

The following table lists the different operators that can be overloaded in each language.

Type

C#

Visual Basic

Addition

+

+

And-also False Test

false

IsFalse

Bitwise Complement

~

Not

Concatenation

+

&

Conjunction

&

And

Conversion

See below

CType

Decrement

--

Not supported

Disjunction

|

Or

Division

/

/

Equality

==

=

Exclusive-Or

^

Xor

Exponentiation

Not supported

^

Greater Than

Greater Than Equal

>=

>=

Increment

++

Not supported

Inequality

!=

<> 

Integer Division

Not supported

\

Left Shift

<< 

<< 

Less Than

Less Than Equal

<=

<=

Modulo

%

Mod

Multiplication

*

*

Negation

!

Not

Or-else True Test

true

IsTrue

Pattern Match

Not supported

Like

Right Shift

>> 

>> 

Subtraction

-

-

Unary Minus

-

-

Unary Plus

+

+

In both languages, a few of these operators must be overloaded in pairs.

Type

C#

Visual Basic

Equality Testing

== and !=

= and <>

Less/Greater

> and <

> and <

Less/Greater Equal

>= and <=

>= and <=

And-also/Or-else

false and true

IsFalse and IsTrue

Operator overloads support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

explicit

Narrowing

extern

Not supported

implicit

Widening

public

Public

static

Shared

Not supported

Overloads

Not supported

Shadows

User-defined conversions are implemented as part of the operator overloading syntax in both languages. In C#, the source type appears in the parameter list, and the target type is used as the operator name. In Visual Basic, CType is used as the operator name for all such conversions. The source type appears in the parameter list, and the target type appears as the return type for the method. In both languages, the type containing the conversion declaration must match either the source or the target type.

C#

class CountMonitor

{

    public static explicit operator int(

        CountMonitor source)

    {

        // ----- Converts CountMonitor to int, then...

        return newInt;

    }

    public static implicit operator CountMonitor(

        int source)

    {

        // ----- Converts int to CountMonitor, then...

        return newCountMonitor;

    }

}

VISUAL BASIC

Class CountMonitor

    Public Shared Narrowing Operator CType(

            ByVal source As CountMonitor) As Integer

        ' ----- Converts CountMonitor to Integer, then...

        Return newInt

    End Operator

    Public Shared Widening Operator CType(

            ByVal source As Integer) As CountMonitor

        ' ----- Converts Integer to CountMonitor, then...

        Return newCountMonitor

    End Operator

End Class

Visual Basic’s Widening modifier is the same as C#’s implicit modifier, while VB’s Narrowing modifier matches C#’s explicit modifier. One of these modifiers must be used in each user-defined conversion declaration.

Operator Precedence and Associativity

When an expression includes more than one operator, both C# and Visual Basic use specific precedence and associativity rules to determine, in the absence of grouping parentheses, which operations to apply first. The following table lists the precedence rules for C#, in order from highest (applied first) to lowest (applied last). Operators at the same precedence level are treated as equal in terms of application order.

Category

Operators

Primary

x.y, f(x), a[x], x++, x--, new, typeof, default, checked, unchecked, delegate, nameof

Unary

+, -, !, ~, ++x, --x, (T)x

Multiplicative

*, /, %

Additive

+, -

Shift

<<, >>

Comparison

<, >, <=, >=, is, as

Equality

==, !=

Conjunction

&

Exclusive disjunction

^

Disjunction

|

Conditional conjunction

&&

Conditional disjunction

||

Coalescence

??

Conditional

?:

Assignment and lambda

=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^= , |=, =>

The following table lists Visual Basic’s operators by order of precedence.

Category

Operators

Await

Await

Exponentiation

^

Unary

+, –

Multiplicative

*, /

Integer division

\

Modulo

Mod

Additive

+, -

Concatenation

&

Shift

<<, >>

Comparison

=, <>, <, <=, >, >=, Is, IsNot, Like, TypeOf...Is, TypeOf...IsNot

Negation

Not

Conjunction

And, AndAlso

Disjunction

Or, OrElse

Exclusive disjunction

Xor

In both languages, assignment operators are right-associative; the right side of the operator is evaluated first. For most other binary operators at the same precedence level, operations are left-associative; the expression on the left-side of the operator is determined first, from left to right. For example, x + y + z is evaluated as (x + y) + z. The two exceptions are C#’s ?: conditional operator and its ?? null coalescence operator, both of which are right-associative. For an example of how this impacts conditional operations, see the “?: Conditional Operator” entry in this chapter.

Operators

The following table lists the operators available in both languages. Use the “See Also” column in this table to locate related entries in this chapter.

C# Operator

Visual Basic Operator

See Also

!

Not

! Negation Operator

!=

<> 

!= Comparison Operator

%

Mod

% Modulo Operator

%=

Not supported

%= Assignment Operator

&

And (Conjunction only)

& Address Operator

& Conjunction Operator

&&

AndAlso

&& Conjunction Operator

&=

Not supported

&= Assignment Operator

*

* (Multiplication only)

* Dereference Operator

* Multiplication Operator

*=

*=

*= Assignment Operator

+

+ or &

+ Addition Operator,

+ Unary-Plus Operator

++

Not supported

++ Increment Operator

+=

+= (Assignment only)

+= Assignment Operator,

+= Event Subscription Operator

-

-

- Subtraction Operator,

- Unary-Minus Operator

--

Not supported

-- Decrement Operator

-=

-= (Assignment only)

-= Assignment Operator

-= Event Unsubscription Operator

->

Not supported

-> Member Access Operator

?.

?.

?. Null Conditional Operator

.

.

. Member Access Operator

/

/ or \

/ Division Operator

/=

/= or \=

/= Assignment Operator

:?

If(x,y,z)

?: Conditional Operator

< Comparison Operator

<< 

<< 

<< Left Shift Operator

<<=

<<=

<<= Assignment Operator

<=

<=

<= Comparison Operator

=

=

= Assignment Operator

==

=

== Comparison Operator

=>

Function(), Sub()

=> Lambda Operator

> Comparison Operator

>=

>=

>= Comparison Operator

>> 

>> 

>> Right Shift Operator

>>=

>>=

>>= Assignment Operator

??

If(x,y)

?? Coalescence Operator

[ ]

( )

[ ] Member Access Operator

^

Xor

^ Exclusive-Or Operator

^=

Not supported

^= Assignment Operator

|

Or

| Disjunction Operator

|=

Not supported

|= Assignment Operator

||

OrElse

|| Disjunction Operator

~

Not

~ Bitwise Complement Operator

See Also

Assignment Operators, Operator Precedence and Associativity

Optional Arguments

In C# method signatures, any parameter that includes an assignment becomes an optional argument to the calling procedure.

C#

// ----- The times parameter is optional, defaulting to 2.

public string CopyText(string original, int times = 2)

Visual Basic optional arguments also include this assignment of a constant expression, as well as the Optional modifier.

VISUAL BASIC

' ----- The times parameter is optional, defaulting to 2.

Public Function CopyText(ByVal original As String,

    Optional ByVal times As Integer = 2) As String

The rules surrounding the use of optional arguments in both languages are similar: no non-optional arguments may appear after an optional argument; parameter arrays and optional arguments cannot be used together; and so on.

See Also

, Punctuator, Arguments and Parameters, Methods

orderby Query Expression Operator (LINQ)

Visual Basic’s Order By query expression operator is identical to C#’s orderby operator. Both languages support a comma-delimited list of sorting fields. Each field is sorted in ascending order by default, or explicitly with the ascending (C#) or Ascending (VB) option. To sort in descending order, use the descending (C#) or Descending (VB) option.

C#

var result = from oneEmployee in Employees

             orderby oneEmployee.FullName descending

             select oneEmployee;

VISUAL BASIC

Dim result = From oneEmployee in Employees

             Order By oneEmployee.FullName Descending

             Select oneEmployee

In C#, the orderby clause must appear before the select clause. Visual Basic offers greater flexibility as to the placement of these clauses within the query expression. In Visual Basic, if the Select clause appears first, any calculated fields it includes become available within the Order By clause.

VISUAL BASIC

Dim result = From oneEmployee in Employees

             Select oneEmployee,

             UpperName = oneEmployee.FullName.ToUpper()

             Order By UpperName Descending

See Also

Query Expressions

out Modifier

C#’s out modifier appears before a method parameter to indicate that data will transfer in one direction from the method to the calling code’s associated argument variable.

C#

public bool PerformUpdate(out string updateDetails)

{

    // ----- In code, assign content to updateDetails.

}

Visual Basic does not have a direct syntax equivalent for out. Instead, use the ByRef modifier, which is more akin to C#’s ref modifier.

VISUAL BASIC

Public Function PerformUpdate(

        ByRef updateDetails As String) As Boolean

    ' ----- In code, assign content to updateDetails.

End Function

The System.Runtime.InteropServices namespace does include an OutAttribute class that can be applied to a Visual Basic parameter to indicate that data comes out of the method through the parameter. However, it does not provide the same level of data enforcement available in the similar C# code.

VISUAL BASIC

' ----- Assumes: Imports System.Runtime.InteropServices

Public Function PerformUpdate(

        <Out> ByRef updateDetails As String) As Boolean

See Also

Arguments and Parameters, Generics

Overloading

In C#, the overloading of methods occurs automatically whenever a type includes two methods with the same name, but different signatures.

C#

public Customer RetrieveCustomer(long customerID)

{

    // ----- Retrieve customer record by numeric ID.

}

public Customer RetrieveCustomer(string email)

{

    // ----- Retrieve customer record by email address.

}

The Visual Basic compiler also handles overloading in this way. However, it also provides the optional Overloads keyword that makes the overloading clearer to anyone reading the code. You do not need to include the Overloads keyword, but if you include it with one of the overloaded methods, you must include it with all of them.

VISUAL BASIC

Public Overloads Function RetrieveCustomer(

        ByVal customerID As Long) As Customer

    ' ----- Retrieve customer record by numeric ID.

End Function

Public Overloads Function RetrieveCustomer(

        ByVal email As String) As Customer

    ' ----- Retrieve customer record by email address.

End Function

See Also

operator Statement

override Modifier

Visual Basic’s Overrides modifier is equivalent to C#’s override modifier.

C#

public override int DetermineSize()

VISUAL BASIC

Public Overrides Function DetermineSize() As Integer

C#’s override modifier applies to method, property, indexer, and event declarations. In Visual Basic, the Overrides modifier cannot be used with event declarations. Also, to override a property, method, or indexer (default property) in VB, the member from the base class must include the Overridable modifier (similar to C#’s virtual modifier), or have derived from a further base member that has that modifier.

param Modifier

See

Attributes

Parameter Arrays

See

params Modifier

Parameters

See

Arguments and Parameters, Methods

params Modifier

Visual Basic’s ParamArray modifier is functionally identical to C#’s params modifier.

C#

public int AverageValue(params int[] values)

VISUAL BASIC

Public Function AverageValue(

    ByVal ParamArray values() As Integer) As Integer

partial Modifier

When applied to classes, structures, and interfaces, C#’s partial modifier allows you to split the type across multiple files. Each piece must include the partial modifier.

C#

// ----- From the first *.cs file.

partial class ComplexContent

{

    // ----- Some members defined here.

}

// ----- From the second *.cs file.

partial class ComplexContent

{

    // ----- Other members defined here.

}

Visual Basic’s Partial modifier does the same thing. You can leave the Partial keyword off of at most one of the portions.

VISUAL BASIC

' ----- From the first *.vb file.

Partial Class ComplexContent

    ' ----- Some members defined here.

End Class

' ----- From the second *.vb file.

Class ComplexContent

    ' ----- Other members defined here. The

    '       "Partial" modifier was left off of this part,

    '       although it could have been retained.

End Class

New with Visual Studio 2015

Visual Basic initially did not allow the Partial modifier to be used with interface declarations. However, this feature has been added starting in 2015. That same update also added support for the Partial modifier on VB’s own Module types.

Partial methods allow you to define a method in one file, and provide its implementation in another file, with both parts belonging to the same partial class.

C#

// ----- From the first *.cs file.

partial class ComplexContent

{

    // ----- "private" is implied.

    partial void RecordTraceData(string data);

}

// ----- From the second *.cs file.

partial class ComplexContent

{

    // ----- Same "partial void" and signature.

    partial void RecordTraceData(string data)

    {

        // ----- Implementation here.

    }

}

VISUAL BASIC

' ----- From the first *.vb file.

Partial Class ComplexContent

    ' ----- Declaration includes no method body.

    '       Always begins with "Partial Private Sub."

    Partial Private Sub RecordTraceData(

        ByVal data As String)

    End Sub

End Class

' ----- From the second *.vb file.

Partial Class ComplexContent

    ' ----- Implementation excludes "Partial" modifier.

    '       Signature must still match.

    Private Sub RecordTraceData(ByVal data As String)

        ' ----- Implementation here.

    End Sub

End Class

C# permits partial methods in both classes and structures. In VB, only classes support partial methods.

Pointers

Visual Basic does not support pointer operations, nor does it support any C# feature that enables pointer functionality.

See Also

* Dereference Operator, -> Member Access Operator, & Address Operator, fixed Modifier, fixed Statement, stackalloc Modifier, unsafe Modifier, unsafe Statement

Preprocessing Directives

See

#define Directive, #error Directive, #if Directive, #line Directive, #pragma Directive, #region Directive, #undef Directive, #warning Directive

private Access Modifier

Visual Basic’s Private access modifier is equivalent to C#’s private access modifier.

See Also

Access Modifiers

Project Properties

C# and Visual Basic offer nearly identical settings through the Project Properties window. Visual Studio presents a tabbed collection of settings, and most of the tabs that exist in C# are found in VB, and in an identical configuration. The set of available tabs and tab features will vary based on the type of project.

This entry describes a few of the differences you will encounter when moving from C# to Visual Basic. To see a list of differences from the perspective of moving from Visual Basic to C#, see the “Project Properties” entry in Chapter 2.

Application Tab

Standalone C# applications begin through a Main method. The Application tab’s Startup Object includes a list of all valid Main methods in your application that can be used as the program’s entry point. You will find a similar field in a Visual Basic project’s Application tab. However, in Windows Forms projects, the default presentation allows you to select a form as the startup object. Even if you add a Main method, it will not appear in the Startup Form list by default (although if you add a compatible Main method to the startup form, it will be used instead of a compiler-generated default Main method). To use a non-form Main method as the entry point in a Visual Basic program, clear the project’s Enable Application Framework field on the Project Properties’ Application tab. This will change the Startup Form field to a Startup Object field, and will display all eligible Main methods.

C# presents various resource management options on the Application tab, only some of which are available in Visual Basic’s Application tab. For the Icon and Manifest option, VB has an Icon field that lets you select the default icon. To access the project’s “app.manifest” file, click the View Windows Settings button on VB’s Application tab.

For C# applications that manage resources through a Win32 resource file, the equivalent configuration in Visual Basic requires the use of the VB compiler’s /win32Resource command line option.

Build Tab

Most of the features on the Build tab appear in Visual Basic’s equivalent Compile tab, although many of the names are altered. In most cases, you should be able to determine fairly quickly what the equivalent field is. Both tabs include an Advanced button, and some of the fields included on the main Build tab in C# (including settings for DEBUG, TRACE, and custom constants) appear within the Advanced portion of VB’s Compile tab.

C#’s Advanced build options include a Check for Arithmetic Overflow/Underflow option. VB’s Advanced compile options include a similar Remove Integer Overflow Checks option. Because integer operations are unchecked by default in C#, but checked by default in VB, selecting these options results in different behavior between the languages. If you check the option in C#, you should leave it unchecked in Visual Basic, and vice versa.

C#’s Allow Unsafe Code, Warning Level, and Advanced / Language Version build options have no equivalent in Visual Basic. The Internal Compiler Error Reporting and File Alignment options, both Advanced build options in C#, can only be performed in Visual Basic via its command line compiler options. Use the /errorreport and /filealign options, respectively.

Build Events Tab

To access these same features in a Visual Basic project, click the Build Events button on the Compile tab.

Reference Paths Tab

The list of reference paths is available in Visual Basic by clicking on the Reference Paths button on the References tab. C# displays project-specific references in a branch of the Solution Explorer. VB also makes project references available in the Solution Explorer, although some editions require that the Show All Files feature of that panel be activated.

Properties

Visual Basic’s Property statement closely parallels C#’s inclusion of member properties. As with other block statements in VB, the getter, setter, and the property itself all include a closing End clause.

C#

// ----- Many properties use backing fields.

private int _maxAmount = 0;

// ----- Here is the property itself.

public int Maximum

{

    get

    {

        return this._maxAmount;

    }

    set

    {

        // ----- A "value" incoming variable is implied.

        if (value > 100)

            this._maxAmount = 100;

        else if (value < 0)

            this._maxAmount = 0;

        else

            this._maxAmount = value;

    }

}

VISUAL BASIC

' ----- Many properties use backing fields.

Private _maxAmount As Integer = 0

' ----- Here is the property itself.

Public Property Maximum As Integer

    Get

        Return Me._maxAmount

    End Get

    Set(ByVal value As Integer)

        ' ----- Although "value" is the default,

        '       you can rename this variable.

        If (value > 100) Then

            Me._maxAmount = 100

        ElseIf (value < 0) Then

            Me._maxAmount = 0

        Else

            Me._maxAmount = value

        End If

    End Set

End Property

Read-only and write-only properties in C# exist by leaving out the unneeded getter or setter. This is also done in Visual Basic, but the ReadOnly or WriteOnly modifier must be part of the property declaration as well.

C#

public int Status

{

    get

    {

        // ----- return statement appears here.

    }

    // ----- But no setter appears.

}

VISUAL BASIC

Public ReadOnly Property Status As Integer

    Get

        ' ----- Return statement appears here.

    End Get

    ' ----- But no setter appears.

End Property

When crafting a read-write property, both languages allow you to apply an access modifier to either the getter or setter (but not both) that differs from the modifier applied to the property itself. Properties are private by default in C# classes and structures, but Publicby default in Visual Basic types.

C#

public int Status

{

    get

    {

        // ----- Publicly accessible getter code.

    }

    private set

    {

        // ----- Privately accessible setter code.

    }

}

VISUAL BASIC

Public Property Status As Integer

    Get

        ' ----- Publicly accessible getter code.

    End Get

    Private Set

        ' ----- Privately accessible setter code.

    End Set

End Property

In C#, when a property explicitly implements an interface member, the name is modified to include the interface name. In Visual Basic, an Implements clause appears after the As clause.

C#

public int IMonitor.Status

VISUAL BASIC

Public Property Status As Integer _

    Implements IMonitor.Status

New with Visual Studio 2015

In 2015, C# added the ability to define properties using lambda expressions.

C#

public string FileAs => LastName + ", " + FirstName;

Visual Basic does not yet support the creation of properties using lambdas.

New with Visual Studio 2015

C# allows a property defined as read-only in an interface to be managed by a full read-write property member in the implementing type. Visual Basic formerly did not allow this combination, but this feature was added to that language starting in 2015.

Properties support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

abstract

MustOverride

extern

Not supported

internal

Friend

new

Shadows

override

Overrides

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

sealed

NotOverridable Overrides, or NotOverridable in base class

static

Shared

virtual

Overridable

Not supported

Default

Not supported

Overloads

Not supported

Iterator

Not supported

ReadOnly

Not supported

WriteOnly

Properties in Visual Basic can include parameters, as with methods. The parameter list appears after the property name in the initial declaration. This method for creating parameterized properties is not supported in C#.

VISUAL BASIC

Public Property Status(ByVal day As DayOfWeek) As Integer

    Get

        ' ----- Return day-specific status.

    End Get

    Set(ByVal value As Integer)

        ' ----- Set day-specific status to value.

    End Set

End Property

In Visual Basic, a property can be passed to a method by reference, something not supported in C#.

See Also

Automatic Properties

property Modifier

See

Attributes

protected Access Modifier

Visual Basic’s Protected access modifier is equivalent to C#’s protected access modifier.

See Also

Access Modifiers

protected internal Access Modifier

Visual Basic’s Protected Friend access modifier is equivalent to C#’s protected internal access modifier.

See Also

Access Modifiers

public Access Modifier

Visual Basic’s Public access modifier is equivalent to C#’s public access modifier.

See Also

Access Modifiers

Query Expressions (LINQ)

Both C# and Visual Basic include native support for many features of LINQ. Each language includes a set of query operators, and many of them have counterparts in the other language. The following table lists the methods supported by LINQ’s Queryable class, and indicates the equivalent query operator available within each language.

Queryable Member

C# Operator

Visual Basic Operator

Aggregate

Not supported

Not supported

All

Not supported

Aggregate...Into All

Any

Not supported

Aggregate...Into Any

AsEnumerable

Not supported

Not supported

AsQueryable

from with TypeName

From...As

Average

Not supported

Aggregate...Into Average

Cast

Not supported

Not supported

Concat

Not supported

Not supported

Contains

Not supported

Not supported

Count

Not supported

Aggregate...Into Count

DefaultIfEmpty

Not supported

Not supported

Distinct

Not supported

Distinct

ElementAt

Not supported

Not supported

ElementAtOrDefault

Not supported

Not supported

Empty

Not supported

Not supported

Except

Not supported

Not supported

First

Not supported

Not supported

FirstOrDefault

Not supported

Not supported

GroupBy

group

Group By

GroupJoin

join...into

Group Join

Intersect

Not supported

Not supported

Join

join

Join

Last

Not supported

Not supported

LastOrDefault

Not supported

Not supported

LongCount

Not supported

Aggregate...Into LongCount

Max

Not supported

Aggregate...Into Max

Min

Not supported

Aggregate...Into Min

OfType

Not supported

Not supported

OrderBy

orderby

Order By

OrderByDescending

orderby

Order By

Range

Not supported

Not supported

Repeat

Not supported

Not supported

Reverse

Not supported

Not supported

Select

from and select

From and Select

SelectMany

from (multiple)

From (multiple)

SequenceEqual

Not supported

Not supported

Single

Not supported

Not supported

SingleOrDefault

Not supported

Not supported

Skip

Not supported

Skip

SkipWhile

Not supported

Skip While

Sum

Not supported

Aggregate...Into Sum

Take

Not supported

Take

TakeWhile

Not supported

Take While

ThenBy

orderby

Order By

ThenByDescending

orderby

Order By

ToArray

Not supported

Not supported

ToDictionary

Not supported

Not supported

ToList

Not supported

Not supported

ToLookup

Not supported

Not supported

Union

Not supported

Not supported

Where

where

Where

Not applicable

let

Let

To see specific examples of these native operators, use the “See Also” block later in this entry to locate related query expression entries in this chapter.

When a specific LINQ method is not supported natively, each language allows that method to be included directly as part of the query expression syntax.

C#

var allNames = (from set1 in oldCustomers

               select set1.FullName).Union(

               from set2 in newCustomers

               select set2.FullName);

VISUAL BASIC

Dim allNames = (From set1 In oldCustomers

               Select set1.FullName).Union(

               From set2 In newCustomers

               Select set2.FullName)

Both languages support the LINQ providers supplied with Visual Studio: LINQ to Objects, LINQ to DataSet, LINQ to Entities, and LINQ to XML. (LINQ to SQL, formerly supported in both languages, has been deprecated in favor of LINQ to DataSet and LINQ to Entities.) Visual Basic’s interaction with LINQ to XML includes the ability to generate new XML content natively as part of its XML Literals support. C# does not include this feature.

LINQ queries in C# support the * transparent identifier as part of its from clause. These transparent identifiers are not supported in Visual Basic.

As with other statements in C#, a query expression that completes a statement must be followed by a semicolon. In Visual Basic, the compiler attempts to detect the end of the statement syntactically. However, there may be times when the compiler will not be able to correctly determine whether the statement that follows a query expression is part of the query or not. In some cases, a blank line must appear between the query expression and the subsequent statement to ensure a proper separation. Also, a line continuation character (_) may be needed within some queries to ensure that all lines of those queries remain connected.

See Also

from Query Expression Operator, group Query Expression Operator, join Query Expression Operator, let Query Expression Operator, orderby Query Expression Operator, select Query Expression Operator, where Query Expression Operator

readonly Modifier

As with C#’s readonly modifier, Visual Basic’s ReadOnly modifier can appear as part of a field definition.

C#

class TaxInformation

{

    // ----- Must be set in a constructor or declaration.

    private readonly int TaxYear;

}

VISUAL BASIC

Class TaxInformation

    ' ----- Must be set in a constructor or declaration.

    Private ReadOnly TaxYear As Integer

End Class

Visual Basic’s ReadOnly modifier can also be used to create a read-only property. In C#, this is done by omitting the property’s setter.

See Also

Properties

ref Modifier

Visual Basic’s ByRef modifier is equivalent to C#’s ref modifier, both of which indicate that an argument is to be passed by reference instead of by value.

C#

public bool ModifyDate(ref DateTime activeDate)

{

    // ----- Use or update activeDate as needed.

}

VISUAL BASIC

Public Function ModifyDate(

        ByRef activeDate As Date) As Boolean

    ' ----- Use or update activeDate as needed.

End Function

In Visual Basic, a property can be passed to a method by reference, something not supported in C#.

See Also

Arguments and Parameters, Generics

return Modifier

See

Attributes

return Statement

Visual Basic’s Return statement is identical in use and syntax to C#’s return statement, both for methods with return values and for those without.

C#

// ----- For methods with void return type.

return;

// ----- For methods with non-void return type.

return someValue;

VISUAL BASIC

' ----- For methods with void return type (Sub).

Return

' ----- For methods with non-void return type (Function).

Return someValue

For methods that do not return a value (Sub methods), Visual Basic also supports the Exit Sub statement, which is functionally equivalent to Return. (A related Exit Property statement exists for properties.)

VISUAL BASIC

' ----- For methods with a void return type.

Exit Sub

For methods that return a value in VB (Function methods), that value can be assigned to the name of the function, and the Exit Function can be used to exit the method early.

VISUAL BASIC

Public Function DetermineValue() As Integer

    Dim theValue As Integer

    ' ----- Calculating logic, then...

    DetermineValue = theValue

    Exit Function

    ' ----- More logic can appear here.

End Function

This variation exists for backward compatibility. The use of the newer Return syntax is recommended.

sbyte Data Type

Visual Basic’s intrinsic SByte data type is identical to C#’s sbyte data type. Both types are aliases for .NET’s System.SByte type.

C#

sbyte offset = 0;

VISUAL BASIC

Dim offset As SByte = 0

Scope

See

Lifetime and Scope

sealed Modifier

When applied to a class, C#’s sealed modifier is the same as Visual Basic’s NotInheritable modifier.

C#

sealed class CoreSettings

VISUAL BASIC

NotInheritable Class CoreSettings

When applied to members of a derived class overriding the matching virtual member in the base class, C#’s sealed modifier is replaced in Visual Basic with the NotOverridable modifier. In both languages, the override (C#) or Overrides (VB) modifier must also be present.

C#

sealed protected override void Refresh()

VISUAL BASIC

Protected NotOverridable Overrides Sub Refresh()

For such members, C#’s sealed modifier can apply to methods, properties, indexers, and events. In Visual Basic, events cannot be marked with the NotOverridable modifier.

select Query Expression Operator (LINQ)

Visual Basic’s Select query expression operator is identical to C#’s select operator. When crafting query expressions in VB, the Select clause is optional, even in situations where its C# counterpart would be required. When Select is left out, the member identified in the From, Aggregate , or Group clause is returned. Additionally, Visual Basic allows more flexibility concerning the placement of the Select clause within the query expression.

C#

var result = from oneEmployee in Employees

             where oneEmployee.IsManager == true

             select oneEmployee;

VISUAL BASIC

' ----- The Select clause can also appear before Where.

Dim result = From oneEmployee In Employees

             Where oneEmployee.IsManager = True

             Select oneEmployee

As in C#, Visual Basic supports the return of anonymous types, either implicitly with a restricted selection list, or explicitly via the New With syntax. You can also create new instances of named types using this same syntax.

C#

// ----- Anonymous type.

var result = from oneEmployee in Employees

             where oneEmployee.IsManager == true

             select new {Name = oneEmployee.FullName,

             oneEmployee.Salary, oneEmployee.HireDate};

// ----- Named type.

var result = from oneEmployee in Employees

             where oneEmployee.IsManager == true

             select new Person {

             Name = oneEmployee.FullName};

VISUAL BASIC

' ----- Anonymous type.

Dim result = From oneEmployee In Employees

             Where oneEmployee.IsManager = True

             Select New With {.Name = oneEmployee.FullName,

             oneEmployee.Salary, oneEmployee.HireDate}

' ----- Named type.

Dim result = From oneEmployee In Employees

             Where oneEmployee.IsManager = True

             Select New Person With {

             .Name = oneEmployee.FullName}

See Also

Query Expressions

set Declaration

See

Properties

Short Circuiting

See

&& Conjunction Operator, || Disjunction Operator, ?: Conditional Operator

short Data Type

Visual Basic’s intrinsic Short data type is identical to C#’s short data type. Both types are aliases for .NET’s System.Int16 type. For short literals, Visual Basic uses an S or s suffix after the value; C# does not include such a suffix.

C#

short baseYear = 0;

VISUAL BASIC

Dim baseYear As Short = 0s  ' or 0S

sizeof Operator

Visual Basic does not include a direct equivalent for C#’s sizeof operator. One option is to use the System.Runtime.InteropServices.Marshal.SizeOf method, which provides similar, though not identical, results. Consider the following table, which compares the output (in bytes) of both sizeof and Marshal.SizeOf using the same data types as arguments. The bool and char types provide different results. Visual Basic also includes a Len method that returns similar, but not identical, results for its intrinsic value types.

C# Type

sizeof

Marshal.SizeOf

Len Method

byte, sbyte

1

1

1

short, ushort

2

2

2

int, uint

4

4

4

long, ulong

8

8

8

bool

1

4

2

char

2

1

2

float

4

4

4

double

8

8

8

decimal

16

16

8

The sizeof operator also returns sizes for pointers and certain structures in unsafe contexts. You can use .NET’s System.IntPtr.Size method in VB to obtain the platform-specific size of a pointer or handle. For structures, the Marshal.SizeOf method will return the total size of the structure type passed to it. This may or may not result in the same value provided by C#’s sizeof operator.

VISUAL BASIC

Dim structSize As Integer =

    Marshal.SizeOf(GetType(structName))

stackalloc Modifier

Visual Basic has no equivalent for C#’s stackalloc modifier.

Statements

In C#, the semicolon determines the end of a statement. For the purposes of statement structure, a block of statements surrounded with a set of curly braces is treated as a single semicolon-terminated statement.

C#

// ----- A simple single-line statement.

quotient = numerator / denominator;

// ----- An if condition, with its subordinate statement.

if (totalPercent > 100)

    totalPercent = 100;

// ----- An if condition with a subordinate block.

if (totalPercent > 100)

{

    ReportOverage(totalPercent);

    totalPercent = 100;

}

In Visual Basic, the end of a physical line indicates where the statement ends. For block statements (such as For loops), opening, closing, and subordinate portions each terminate at the end of a physical line, although multiple statements may appear within the subordinate block.

VISUAL BASIC

' ----- A simple single-line statement.

quotient = numerator / denominator

' ----- An If condition, with its subordinate statement.

If (totalPercent > 100) Then

    totalPercent = 100

End If

' ----- An If condition with a subordinate block.

If (totalPercent > 100) Then

    ReportOverage(totalPercent)

    totalPercent = 100

End If

C# allows a single logical line to span physical lines by employing as much or as little whitespace as needed, as long as the entire statement ends with a semicolon.

C#

expirationDate = string.Format("{0:00}/{1:0000}",

    monthPortion, yearPortion);

Traditionally, Visual Basic accomplishes this by adding a line continuation character (an underscore preceded by at least one space character) to the end of all lines except the last in a logical statement.

VISUAL BASIC

expirationDate = String.Format("{0:00}/{1:0000}", _

    monthPortion, yearPortion)

Newer editions of Visual Basic do a better job at determining when two physical lines constitute a logical statement, even in the absence of the line continuation character. In general, when a line ends with a clearly incomplete statement—such as a set of parentheses being left open—the VB compiler will assume that the line continues, even when not explicitly indicated.

VISUAL BASIC

' ----- A line ending in a comma indicates continuation.

expirationDate = String.Format("{0:00}/{1:0000}",

    monthPortion, yearPortion)

C# allows multiple statements to sit on a single physical line.

C#

// ----- Two simple statements on one line.

firstName = "John"; lastName = "Doe";

// ----- A block statement can be single-line as well.

while (status > 0) status = DoMoreWork();

To do this in Visual Basic, you must connect the statements with a colon character.

VISUAL BASIC

' ----- Two simple statements on one line.

firstName = "John" : lastName = "Doe"

' ----- A block statement can be single-line as well.

Do While (status > 0) : status = DoMoreWork() : Loop

A special case of this statement joining in VB occurs in the single-line form of the If statement, where linked statements are processed in response to the condition.

VISUAL BASIC

' ----- Both assignments will occur if true.

If (counter > 100) Then overflow = True : counter = 0

In C#, these subordinate statements must be enclosed in a set of curly braces. Using a syntax that more closely parallels that of VB will produce the wrong results.

C#

// ----- This is equivalent to the earlier VB code.

if (counter > 100) { overflow = true; counter = 0; }

// ----- This code is wrong; counter will be reset

//       whether the condition is true or false.

if (counter > 100) overflow = true; counter = 0;

C# permits you to start a distinctly scoped block by using a set of curly braces without an associated block construct.

C#

{

    // ----- Code here is locally scoped.

}

There is no built-in way to accomplish this in Visual Basic, although you can simulate by using a superfluous If statement.

VISUAL BASIC

If (True) Then

    ' ----- Code here is locally scoped.

End If

As with other Visual Basic statements, LINQ queries can span multiple physical lines, explicitly using line continuation characters, or implicitly when the context leads to implicit line continuation. However, it is possible to design a query for which the end of the statement is not easily recognized by the VB compiler. In such cases, you must leave a blank line after the query before beginning the next logical statement.

See Also

; Statement Termination Character

static Modifier

C#’s static modifier, when attached to a class or to individual members of a structure or class, identifies members (or an entire class’ members) that are accessible outside of any specific instance of that class. When a class uses static as part of its declaration, all of its members must also be marked as static.

C#

static class CoreFeatures

{

    public static void LogError(string errorText)

    {

        // ----- Callable as CoreFeatures.LogError()

    }

}

In Visual Basic, the Shared modifier performs the same function. However, it can only be attached to class and structure members, not to the class itself.

VISUAL BASIC

Class CoreFeatures

    Public Shared Sub LogError(ByVal errorText As String)

        ' ----- Callable as CoreFeatures.LogError()

    End Sub

End Class

If every member of the class will be shared, you can use a Visual Basic Module statement. All members of modules are implicitly shared, as with a static class in C#. Therefore, the Shared modifier does not appear in this context.

VISUAL BASIC

Module CoreFeatures

    Public Sub LogError(ByVal errorText As String)

        ' ----- Implicitly shared. Callable as LogError()

    End Sub

End Module

Visual Basic does include a Static statement. It is used to declare local variables, just like the Dim statement, but the lifetime of static variables is the lifetime of the instance (when found in instance methods of classes and structures) or the application (when found in modules, or in static methods of classes and structures).

VISUAL BASIC

Public Sub ProcessData()

    ' ----- Track errors over multiple calls.

    Static countErrors As Integer = 0

    Try

        ' ----- Processing logic here.

    Catch ex As System.Exception

        countErrors += 1

        If (countErrors >= 5) Then Throw

    End Try

End Sub

C# does not include support for local static variables. Such variables must appear as type-level fields instead.

string Data Type

Visual Basic’s intrinsic String data type is identical to C#’s string data type. Both types are aliases for .NET’s System.String type.

C#

string name = "";

VISUAL BASIC

Dim name As String = ""

Historically, Visual Basic has provided a $ suffix that could be attached to string identifiers or certain intrinsic functions. Although the .NET versions of Visual Basic still support this for backward compatibility, its use is not recommended.

struct Statement

Visual Basic’s Structure statement is equivalent to C#’s struct statement. When declaring a structure that implements one or more interfaces, VB’s Implements clause lists those interfaces, appearing as the first line within the Structure statement.

C#

struct Variable : IDataPart

{

    // ----- Members appear here.

}

VISUAL BASIC

Structure Variable

    Implements IDataPart

    ' ----- Members appear here.

End Structure

Structures in both languages contain the same types of members: constructors, fields, constants, properties, methods, operator overloads and user-defined conversions, indexers, events, and nested types (including delegates and enumerations). Instance fields within a structure cannot include an initialization value with the declaration, but static fields can.

Structures support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

internal

Friend

new

Shadows

partial

Partial

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

Structures in C# are internal by default, just as structures in Visual Basic are Friend by default. C# structure members are private by default; they are Public by default in VB. Structure members cannot use the protected (C#) or Protected (VB) modifier.

See Also

Access Modifiers, Constructors

switch Statement

Visual Basic’s Select Case statement is generally equivalent to C#’s switch statement. Both statements include “case” blocks, plus an optional default/else block.

C#

switch (position)

{

    case 1:

        positionName = "ones";

        break;

    case 10:

        positionName = "tens";

        break;

    case 100:

        positionName = "hundreds";

        break;

    default:

        positionName = "too large!";

        break;

}

VISUAL BASIC

Select Case position

    Case 1

        positionName = "ones"

    Case 10

        positionName = "tens"

    Case 100

        positionName = "hundreds"

    Case Else

        positionName = "too large!"

End Select

As with other C# block statements, the condition that appears after the switch keyword must be enclosed in parentheses. The parentheses are optional in VB. C#’s case clause becomes Case with no trailing colon; default becomes Case Else. In both languages, the first block that matches is used; those that follow, even if they match the test value, will be skipped.

Each case block in C# must be explicitly exited using a break statement or some other exiting statement. In Visual Basic, a matched block is automatically exited after its last statement; no equivalent for break is needed. You can also exit a C# case block using a goto case or goto default statement.

C#

case DayOfWeek.Monday:

    // ----- Day-specific processing, then...

    goto default;

default:

    // ----- General processing.

To do the same thing in Visual Basic, use a standard GoTo statement with a line label placed in the target Case block.

VISUAL BASIC

Case DayOfWeek.Monday

    ' ----- Day-specific processing, then...

    GoTo DoDefault

Case Else

DoDefault:

    ' ----- General processing.

In C#, the case clauses each contain a single comparison value: an integer number, a character or string, a Boolean literal, an enumeration member, or null . Visual Basic adds floating-point numbers, dates, and general Object instances to the list. In C#, two values can trigger the same block of matching code by placing their case clauses next to each other.

C#

case DayOfWeek.Monday:

case DayOfWeek.Wednesday:

    // ----- Day-specific processing.

In Visual Basic, both values can appear in a single Case clause, separated by commas. Also, VB supports value ranges, expressions, and relative comparisons.

VISUAL BASIC

Case 1, 2

    ' ----- Matches one of the comma-delimited values.

    tableSize = "small"

Case 3 To 6

    ' ----- Matches inclusive range.

    tableSize = "medium"

Case TableForSeven()

    ' ----- Matches result of expression or method call.

    tableSize = "oddball"

Case Is > 7

    ' ----- Matches using comparison operator.

    tableSize = "large"

For the comparison operator method, the Is keyword is followed by one of =, <>, < , <=, >, or >= , and then a comparison value. When comparing string values, the current state of the Option Compare statement will impact the comparison.

You can mix any number of comparison alternatives by including them in a single comma-delimited list.

VISUAL BASIC

Case 1, 3 To 6, 3 * 12, SpecialValue(), Is >= 100

The associated block will execute if any of the comma-delimited values match the test value. That is, they are implicitly connected with an Or comparison operator. Because of this, take care when using more than one Is keyword.

VISUAL BASIC

Case Is >= 100, Is <= 500

This will match all values, since every value is either more than 100 or less than 500. Instead, you should use a 100 To 500 range specification instead.

See Also

goto Statement

Ternary Operator

See

?: Conditional Operator

this Constructor Declaration

C#’s this constructor declaration, when attached to an instance constructor, calls another of the type’s instance constructors before processing its own logic.

C#

class Person

{

    public string FullName;

    public int CurrentAge;

    public Person(string name)

    {

        FullName = name;

    }

    public Person(string name, int age) : this(name)

    {

        CurrentAge = age;

    }

}

Visual Basic does not have a direct equivalent for this syntax. Instead, you must call one constructor from the other.

VISUAL BASIC

Class Person

    Public FullName As String

    Public CurrentAge As Integer

    Public Sub New(ByVal name As String)

        Me.FullName = name

    End Sub

    Public Sub New(ByVal name As String,

            ByVal age As Integer)

        Me.New(name)

        Me.CurrentAge = age

    End Sub

End Class

See Also

base Constructor Declaration, Constructors

this Extension Method Modifier

See

Extension Methods

this Indexer Declaration

C# uses this as part of a property declaration to define an indexer.

C#

public string this[int index]

{

    get

    {

        return InternalStorage[index];

    }

    set

    {

        // ----- "value" is implicitly defined.

        InternalStorage[index] = value;

    }

}

In Visual Basic, indexers are known more commonly as “default properties,” due in part to the use of the Default modifier on the property definition. Unlike other property modifiers, Default appears before the access modifier.

VISUAL BASIC

' ----- You may indicate the name, "Item" in this case.

Default Public Property Item(

        ByVal index As Integer) As String

    Get

        Return InternalStorage(index)

    End Get

    Set(ByVal value As String)

        ' ----- If the "value" declaration is omitted,

        '       "value" will be implicitly defined as in

        '       C#. When present, you can alter its name.

        InternalStorage(index) = value

    End Set

End Property

Both languages support overloading of the indexer via a different argument signature. The name of the property must be the same across all overloads in VB, and Default must appear as a modifier in each overload. Both languages allow indexers to appear in classes, structures, or interfaces.

C#

// ----- Interface-based indexer.

interface IIndexed

{

    string this[int index] {get; set;}

}

VISUAL BASIC

' ----- Interface-based indexer.

Interface IIndexed

    Default Property Item(ByVal index As Integer) As String

End Interface

New with Visual Studio 2015

In 2015, C# added the ability to define indexers using lambda expressions.

C#

public Order this[long orderID] =>

    LookupOrderByID(orderID);

Visual Basic does not yet support the creation of default properties using lambdas.

In addition to Visual Basic’s Default modifier, indexers support the following modifiers in each language.

C# Modifier

Visual Basic Modifier

abstract

MustOverride

extern

Not supported

internal

Friend

new

Shadows

override

Overrides

private

Private

protected

Protected

protected internal

Protected Friend

public

Public

sealed

NotOverridable Overrides,

or NotOverridable in base class

virtual

Overridable

Not supported

ReadOnly

Not supported

WriteOnly

See Also

[ ] Member Access Operator, Properties

this Instance Expression

Visual Basic’s Me expression provides access to members of the local type, just like C#’s this expression.

C#

class SimpleAdder

{

    public int Value = 0;

    public void Increment()

    {

        this.Value++;

    }

}

VISUAL BASIC

Class SimpleAdder

    Public Value As Integer = 0

    Public Sub Increment()

        Me.Value += 1

    End Sub

End Class

Visual Basic also includes a MyClass expression that is similar to Me, but where Me would reference overridden members in derived classes when relevant, MyClass always references members as they were originally defined in the current class. There is no C# equivalent for MyClass.

throw Statement

Visual Basic’s Throw statement is identical to C#’s throw statement.

C#

throw new System.Exception("Something bad happened.");

VISUAL BASIC

Throw New System.Exception("Something bad happened.")

Within the catch block of a try statement, the throw statement can be used by itself (without any operand) to re-throw the catch block’s exception.

C#

catch (System.Exception ex)

{

    // ----- Local logic, then...

    throw;

}

Visual Basic supports this same syntax.

VISUAL BASIC

Catch ex As System.Exception

    ' ----- Local logic, then...

    Throw

true Boolean Literal

When limited to Boolean operations, Visual Basic’s True literal is identical to C#’s true literal. When a Boolean value is converted or cast to an integer, C#’s true value will always become 1 (one). In VB, True will become 1 or -1 depending on the type of cast or conversion. See the “bool Data Type” in this chapter for details.

See Also

bool Data Type

try Statement

Visual Basic’s Try statement is generally equivalent to C#’s try statement.

C#

try

{

    customerRecord = RetrieveCustomer(customerID);

}

catch (System.Expression ex)

{

    LogError("Problem with customer record.", ex);

    return;

}

finally

{

    InProcessField.Visible = false;

}

VISUAL BASIC

Try

    customerRecord = RetrieveCustomer(customerID)

Catch ex As System.Expression

    LogError("Problem with customer record.", ex)

    Return

Finally

    InProcessField.Visible = False

End Try

Both languages share a common set of rules surrounding the use of try/catch statements: at least one catch or finally block must appear; nesting is supported; jumps into any of the blocks from outside are restricted; multiple catch blocks may appear, and are processed in order; and so on.

New with Visual Studio 2015

Beginning in 2015, catch clauses in C# can include conditions that limit access to a given exception handler. Visual Basic already included support for this same functionality through its When clause.

C#

try

{

    customerRecord = RetrieveCustomer(customerID);

}

catch (System.Exception ex) if (errorCount < 5)

{

    errorCount += 1;

    LogWarning("Problem with customer record.", ex);

}

catch (System.Exception ex) if (errorCount >=5)

{

    LogFatalError("Problem with customer record.", ex);

    return;

}

VISUAL BASIC

Try

    customerRecord = RetrieveCustomer(customerID)

Catch ex As System.Exception When (errorCount < 5)

    errorCount += 1

    LogWarning("Problem with customer record.", ex)

Catch ex As System.Exception When (errorCount >=5)

    LogFatalError("Problem with customer record.", ex)

    Return

End Try

Visual Basic includes an Exit Try statement that can be used in a Try or Catch block (but not a Finally block) to exit the innermost Try structure. Execution continues with the statement after the entire Try statement; the Finally block, when present, will be processed. In C#, such a jump out of the try statement requires a line label after the statement, and the use of goto to perform the jump out of the try or catch block.

type Modifier

See

Attributes

typeof Operator

Visual Basic’s GetType operator is identical to C#’s typeof operator.

C#

System.Type numberType = typeof(int);

VISUAL BASIC

Dim numberType As System.Type = GetType(Integer)

uint Data Type

Visual Basic’s intrinsic UInteger data type is identical to C#’s uint data type. Both types are aliases for .NET’s System.UInt32 type. For unsigned integer literals, C# uses a U or u suffix after the value; in Visual Basic, use UI or ui instead.

C#

uint counter = 0u;

VISUAL BASIC

Dim counter As UInteger = 0UI  ' or 0ui

ulong Data Type

Visual Basic’s intrinsic ULong data type is identical to C#’s ulong data type. Both types are aliases for .NET’s System.UInt64 type. For unsigned long literals, both C# and Visual Basic use a UL suffix after the value, or some uppercase/lowercase variation of UL.

C#

ulong counter = 0ul;

VISUAL BASIC

Dim counter As ULong = 0UL

unchecked Expression

C#’s unchecked keyword, whether in its statement-block form or expression form, disables run-time integer overflow checking on the contained statements or expression.

Visual Basic enables integer overflow checking by default on a project-wide basis. To enable or disable overflow checking, access the Advanced Compiler Settings within the Project Properties, and set the Remove Integer Overflow Checks field as needed. VB does not include the ability to control integer overflow checks at the statement or expression level.

unsafe Expression

C#’s unsafe expression, whether in its statement-block or modifier form, indicates a section of unsafe (unmanaged) code. Because Visual Basic does not support unsafe contexts, it has no equivalent for unsafe.

ushort Data Type

Visual Basic’s intrinsic UShort data type is identical to C#’s ushort data type. Both types are aliases for .NET’s System.UInt16 type. For unsigned short literals, Visual Basic uses a US suffix after the value, or some uppercase/lowercase variation of US; C# does not include such a suffix.

C#

ushort counter = 0;

VISUAL BASIC

Dim counter As UShort = 0US

using Directive

C#’s using directive identifies namespaces that will be used within the current source file without the need to provide the full, absolute namespace path to its members.

C#

// ----- At the top of a source code file.

using System.Text;

// ----- Later, in a method in the same file, you don't

//       need the full System.Text.StringBuilder path.

StringBuilder content = new StringBuilder();

Visual Basic’s Imports statement performs this same identification of namespaces.

VISUAL BASIC

' ----- At the top of a source code file.

Imports System.Text

' ----- Later, in a method in the same file, you don't

'       need the full System.Text.StringBuilder path.

Dim content As New StringBuilder()

Both languages support the assignment of alias names to imported namespaces (and imported types in Visaul Basic).

C#

using TextStuff = System.Text;

VISUAL BASIC

Imports TextStuff = System.Text

The alias can be prefixed to member names within that same file.

C#

TextStuff.StringBuilder content =

    new TextStuff.StringBuilder();

VISUAL BASIC

Dim content As New TextStuff.StringBuilder()

Visual Basic also provides project-wide importing of namespaces, allowing programmers to reference such namespaces without the need to include an Imports statement in every file. Relevant namespaces are imported by default into new projects through this feature. To access the list of project-wide imports, open the Project Properties panel, access the References tab, and use the Imported Namespaces field to select those namespaces that should be imported across your project.

New with Visual Studio 2015

Starting in 2015, C#’s using static directive can specify a static type (or an instance type with static members), such as an enumeration or a static class. This allows your code to reference members of those types without a full namespace qualification. Visual Basic’sImports statement has always included this same functionality.

C#

using static System.Drawing.SystemColors;

// ----- Later, in method code in the same file, members

//       of SystemColors can be used directly.

displayColor = ControlText;

VISUAL BASIC

Imports System.Drawing.SystemColors

' ----- Later, in method code in the same file, members

'       of SystemColors can be used directly.

displayColor = ControlText

using Statement

Visual Basic’s Using statement is generally equivalent to C#’s using statement. C# requires parentheses around the block variable declaration, but they are optional in VB.

C#

using (SqlConnection myDB = new SqlConnection(dbPath))

{

    // ----- myDB is disposed on exit of using block.

}

VISUAL BASIC

Using myDB As SqlConnection = New SqlConnection(dbPath)

    ' ----- myDB is disposed on exit of Using block.

End Using

' ----- This compressed format is also supported.

Using myDB As New SqlConnection(dbPath)

End Using

Both languages allow multiple resources to be created at once in the same using or Using statement. The compiler converts these to nested blocks, which are also permitted in each language. In C#, all variables declared with the same using statement must be of the same data type; VB allows these variables to be of different types.

C#

using (Type1 firstVal = new Type1(),

    secondVal = new Type1())

VISUAL BASIC

' ----- Variables of the same type.

Using firstVal As New Type1, secondVal As New Type1

' ----- Variables of different types.

Using firstVal As New Type1, secondVal As New Type2

var Implicit Type

C#’s var keyword allows your code to create a strongly type variable whose type is determined by context. Such values are commonly used as recipients of LINQ queries, since those statements return anonymous types.

C#

// ----- These two statements create an int and an

//       anonymous type with two members.

var basicValue = 10;

var moreComplex = new { ID = 10, Name = "Ten" };

In Visual Basic, the standard Dim declaration keyword, when used without an As clause, accomplishes this same purpose.

VISUAL BASIC

Dim basicValue = 10

Dim moreComplex = New With { .ID = 10, .Name = "Ten" }

To enable this implicit typing, VB requires that the Option Infer On statement be used, either at the top of the relevant source file, or configured for all files through the project’s properties.

See Also

Query Expressions

Variables

In C#, local variables appear without any special keyword.

C#

int basicValue;          // No initializer

string greeting = "hi";  // With initializer

byte[] storage;          // Array

In Visual Basic, the Dim statement declares local variables.

VISUAL BASIC

Dim basicValue As Integer      ' No initializer

Dim greeting As String = "hi"  ' With initializer

Dim storage() As Byte          ' Array

Just like in C#, VB allows multiple variables to be declared in a single statement, using a comma to separate the identifiers.

C#

// ----- Both variables typed as DateTime.

DateTime startDate, endDate;

// ----- Different types require different statements.

int i1, i2, i3;

short s4, s5;

VISUAL BASIC

' ----- Both variables typed as Date.

Dim startDate, endDate As Date

' ----- Three Integer, two Short

Dim i1, i2, i3 As Integer, s4, s5 As Short

In C#, all variables must be assigned an initial value before they can be used elsewhere in code. In Visual Basic, all variables are initialized automatically to their default values: Nothing for reference types; some variation of zero for intrinsic value types and enumerations; and an instance with initialized members for structures.

Inferred variables in C# use the var instance type.

C#

// ----- Inferred as string.

var message = "Hello, world.";

In Visual Basic, you use the standard Dim statement, but leave off the As clause to trigger local type inference. Option Infer On must be used at the file or project level for this to work.

VISUAL BASIC

' ----- Inferred as string.

Dim message = "Hello, world."

Locally defined variables in VB can be used as the iteration variable in a For Each loop. In C#, the iteration variable must be defined as part of the foreach loop declaration itself.

See Also

[ ] Array Declaration, const Statement, Fields, Identifiers, Initializers, Lifetime and Scope, var Implicit Type

virtual Modifier

Visual Basic’s Overridable modifier is equivalent to C#’s virtual modifier.

C#

public virtual long DetermineImpact()

VISUAL BASIC

Public Overridable Function DetermineImpact() As Long

C#’s virtual modifier can be used with class methods, properties, indexers, and events. In Visual Basic, the Overridable modifier cannot be used with events.

void Data Type

When used as the return type for a method, C#’s void intrinsic data type indicates that no value will be returned from that method.

C#

public void UpdateStatistics()

{

    // ----- May include a return with no value.

    return;

}

In Visual Basic, use the Sub keyword to indicate a method with no return value.

VISUAL BASIC

Public Sub UpdateStatistics()

    ' ----- May include a return with no value.

    Return

End Sub

The void type can also be used in C# to indicate a pointer for which the true type is unknown. Because Visual Basic does not include support for pointers, this use of void has no direct equivalent in VB. Although void is an alias for .NET’s System.Void type, the use of that type is very limited in Visual Basic.

volatile Modifier

Visual Basic does not include a direct substitute for C#’s volatile modifier. To protect access to a local variable in your code, consider using VB’s SyncLock statement, or use other .NET Framework features that allow a thread to safely manage access to a shared resource.

where Clause

In C# generics, conditions can be placed on type parameters with the where clause.

C#

// ----- Clause applied to one type parameter.

class SingleGeneric<T> where T : IEnumerable

// ----- Constraints applied to two type parameters

//       requires two where clauses.

class DoubleGeneric<T, U>

    where T : IEnumerable

    where U : IDisposable

In Visual Basic, the As clause parallels C#’s where clause, and appears immediately after the type parameter being constrained.

VISUAL BASIC

' ----- Clause applied to one type parameter.

Class SingleGeneric(Of T As IEnumerable)

' ----- Constraints applied to two type parameters

'       requires two As clauses.

Class DoubleGeneric(Of T As IEnumerable, U As IDisposable)

To apply multiple constraints to a single parameter, enclose the comma-delimited VB constraints within a set of curly braces.

C#

class ComplexGeneric<T> where T : class, IDisposable

VISUAL BASIC

Class ComplexGeneric(Of T As {class, IDisposable})

Both languages support the same types of constraints on parameters. The following table lists the equivalent constraints.

Constraint

C#

Visual Basic

Specific type

Customer

Customer

Specific interface

IEnumerable

IEnumerable

Another type parameter

U

U

Any class

class

Class

Any structure

struct

Structure

Class with default constructor

new()

New

See Also

Generics

where Query Expression Operator (LINQ)

Visual Basic’s Where query expression operator is identical to C#’s where operator. As in C#, Visual Basic’s Where clause supports the full set of language-specific logical operators.

C#

var result = from oneEmployee in Employees

             where oneEmployee.IsManager == true

             select oneEmployee;

VISUAL BASIC

' ----- The Select clause can also appear before Where.

Dim result = From oneEmployee in Employees

             Where oneEmployee.IsManager = True

             Select oneEmployee

In C#, the where clause must appear before the select clause. Visual Basic offers greater flexibility as to the placement of these clauses within the query expression.

See Also

Query Expressions

while Statement

C#’s while statement loops while a condition is true, and may not loop at all if the condition is initially false.

C#

while (content.Length > 0)

{

    content = ProcessChunkOfContent(content);

}

In Visual Basic, the Do statement accomplishes the same thing when the condition appears at the top of the loop.

VISUAL BASIC

Do While content.Length > 0

    content = ProcessChunkOfContent(content)

Loop

A variation of this loop uses the Until clause instead of While.

VISUAL BASIC

Do Until content.Length = 0

    content = ProcessChunkOfContent(content)

Loop

In both cases, the parentheses surrounding the condition are optional, although they are required in C#.

See Also

do Statement

XML Documentation Comments

Both C# and Visual Basic support XML comments as a means of documenting code and prompting Visual Studio’s IntelliSense to display extended information about types and type members. In C#, these comments begin with the /// symbol.

C#

/// <summary>

///   Tracks details about living creatures.

/// </summary>

class Animal

{

}

In Visual Basic, use the ''' symbol instead.

VISUAL BASIC

''' <summary>

'''   Tracks details about living creatures.

''' </summary>

Class Animal

End Class

C# also allows XML comments within multi-line comment blocks, by starting the block with the /** symbol. This variation has no equivalent in Visual Basic.

C#

/** <summary>

    ...

  */

Both languages use the same set of recommended XML tags for documenting code. See Microsoft’s MSDN documentation for information on using these tags in your projects.

yield Statement

When defining a method iterator or get-accessor iterator, C#’s yield return statement identifies the next value to emit. The related yield break statement aborts an iterator early, before any other logic in the iterator code can run.

C#

// ----- Assumes a LimitedEdition value defined elsewhere.

public IEnumerable<int> SmallNumbers()

{

    yield return 1;

    yield return 2;

    yield return 3;

    if (LimitedEdition)

        yield break;

    yield return 4;

    yield return 5;

}

In Visual Basic, the Yield statement returns the next iterator value, and appears in a function or property that includes the Iterator modifier. VB’s standard Return statement (or the older Exit Function and Exit Property statements) takes the place of C#’s yield breakstatement.

VISUAL BASIC

' ----- Assumes a LimitedEdition value defined elsewhere.

Public Iterator Function SmallNumbers() As _

        IEnumerable(Of Integer)

    Yield 1

    Yield 2

    Yield 3

    If (LimitedEdition) Then Return

    Yield 4

    Yield 5

End Function

If a yield statement appears in a C# try statement, that statement cannot have catch clauses, only a finally clause. Visual Basic allows Try statements that contain Yield statements to use both Catch and Finally clauses.

See Also

Iterators