Following on from Jeff Atwood’s post
about comparing a string to empty string (“”), I found out that C# and
VB.net do not behave the same when comparing a string that is null.
In the following C# snippet, the code will display The String is NOT Null:
string s = null;
if (s == “”)
Console.WriteLine(“The String IS Null”);
else
Console.WriteLine(“The String is NOT Null”);
The following VB.net code will display The String IS Null:
Dim s as string = Nothing
If s = “” Then
Console.WriteLine(“The String IS Null”)
else
Console.WriteLine(“The String is NOT Null”)
End If
The IL for the C# code is:
.method private hidebysig static void
Main(string[] args) cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor()
= ( 01 00 00 00 )
// Code size 38 (0x26)
.maxstack 2
.locals init (string V_0)
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldstr “”
IL_0008:
call bool
[mscorlib]System.String::op_Equality(string,string)
IL_000d: brfalse.s IL_001b
IL_000f: ldstr “The String IS Null”
IL_0014:
call void
[mscorlib]System.Console::WriteLine(string)
IL_0019: br.s IL_0025
IL_001b: ldstr “The String is NOT Null”
IL_0020:
call void
[mscorlib]System.Console::WriteLine(string)
IL_0025: ret
} // end of method Class1::Main
The IL for the VB.net code is:
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() =
( 01 00 00 00 )
// Code size 46 (0x2e)
.maxstack 3
.locals init ([0] string s)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldstr “”
IL_0009: ldc.i4.0
IL_000a:
call int32
[Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.
StringType::StrCmp(string,string,bool)
IL_000f: ldc.i4.0
IL_0010: bne.un.s IL_001f
IL_0012: ldstr “The String IS Null”
IL_0017:
call void
[mscorlib]System.Console::WriteLine(string)
IL_001c: nop
IL_001d: br.s IL_002b
IL_001f: nop
IL_0020: ldstr “The String is NOT Null”
IL_0025:
call void
[mscorlib]System.Console::WriteLine(string)
IL_002a: nop
IL_002b: nop
IL_002c: nop
IL_002d: ret
} // end of method Module1::Main
As we can see from the VB.net IL, the string comparison is replaced
with a call to
Microsoft.VisualBasic.CompilerServices.StringType::StrCmp. From further
reading I understand that Microsoft did this to maintain compatibility
with VB6. The C# compiler on the other hand uses op_Equality to check
the equality of empty string and null. Since null and empty string are
not equal C# returns false from the condition.
So, the debate about whether to use S == “”
or not just about performance, but also about expected operational
behavior. Developers who switch between C# and VB.net could find some
unexpected results in their software if they are not aware of this
idiosyncrasy.
Going back to performance…. Chris Taylor has some nice graphs on
his blog, which show the significant differences in time between S1 == S2, S1.op_Equality(S1), S1.Equals(S1) and String.Equals(S1, S2). Performance varied by test but S1.op_Equality(S1) seemed to be an overall god performer, which is real handy because it’s what the C# compiler chooses when optimizing S1 == S2.
As much as I hate to see code, which doesn’t read as one would expect, VB.net programmers might want to consider using String.Equals(S1, S2) or S1.Length > 0 when doing lots of string comparisons.
In both C# and VB.net worlds, it’s good development practice to check
your strings against null before performing equality operations. Never
assume the compiler is always going to do the work for you – oh it
brings me back to my C++ days when the compiler did crap for you.
In comparing how c# and VB.net does comparisons try looking up:
<br>Option Compare Binary
Can you help me with my code.I am creating a dynamic table with radiobuttons. I am also storing the radiobutton values in an array.But i am not able to get the selected id of a radiobutton to go to the next page.appreciate your time and help
Option Explicit On
Imports System
Imports Microsoft.Win32
Imports System.Web.UI.WebControls.TableCell
Imports System.Web.UI.WebControls.RadioButton
Imports System.Web.UI.WebControls.ListBox
Public Class WebForm2
Inherits System.Web.UI.Page
#Region ” Web Form Designer Generated Code ”
‘This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
End Sub
Protected WithEvents Label1 As System.Web.UI.WebControls.Label
Protected WithEvents DataGrid1 As System.Web.UI.WebControls.DataGrid
Protected WithEvents DataGrid2 As System.Web.UI.WebControls.DataGrid
Protected WithEvents Button1 As System.Web.UI.WebControls.Button
Protected WithEvents dt As System.Web.UI.WebControls.Table
‘NOTE: The following placeholder declaration is required by the Web Form Designer.
‘Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
‘CODEGEN: This method call is required by the Web Form Designer
‘Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim regKey2 As RegistryKey
Dim regkey1 As RegistryKey
Dim Str1, Str2, Str3, Strres As String
Dim i, value1, value2, value3
Dim StringResult As String
Str1 = “S501”
Str3 = “SRS002”
For i = 1 To 8
Dim radMachines As New RadioButton
Dim item, ch As String
radMachines.ID = “rbl_” & i
radMachines.GroupName = “storeinfo”
‘radMachines.Checked = True
‘radMachines.AutoPostBack = True
item = radMachines.ID.ToString
ch = “|”
StringResult = String.Concat(item, ch)
Dim drow2 As New TableRow
Dim ps0 As New TableCell
Dim ps1 As New TableCell
Dim ps2 As New TableCell
Dim ps3 As New TableCell
Dim ps4 As New TableCell
Dim strtry As String
regkey1 = Registry.LocalMachine.OpenRemoteBaseKey(RegistryHive.LocalMachine, String.Concat(Str1, i, Str3))
regKey2 = regkey1.OpenSubKey(“SoftwareJCPENNEYJCPQUEUEApplPSDALG”, True)
Strres = String.Concat(Str1, i, Str3)
value1 = regKey2.GetValue(“PSQueueName”)
value2 = regKey2.GetValue(“RecvQMName”)
value3 = regKey2.GetValue(“SendQMName”)
ps0.Controls.Add(radMachines)
ps1.Controls.Add(New LiteralControl(Strres))
ps2.Controls.Add(New LiteralControl(value1))
ps3.Controls.Add(New LiteralControl(value2))
ps4.Controls.Add(New LiteralControl(value3))
drow2.Cells.Add(ps0)
drow2.Cells.Add(ps1)
drow2.Cells.Add(ps2)
drow2.Cells.Add(ps3)
drow2.Cells.Add(ps4)
dt.Rows.Add(drow2)
‘Response.Write(StringResult)
‘Need help after this line.
Dim a(8) As String
Dim Str = “”
Dim j As Integer
a = StringResult.Split(“|”)
‘For j = 1 To j = 8
If Page.IsPostBack = True Then
If Request.Params(radMachines.ID.ToString) <> Nothing Then
Str = Request.Params(radMachines.ID.ToString)
If a(1) = Str Then
Response.Write(a(1))
End If
‘ElseIf Request.Params(a(1)) <> Nothing Then
‘Response.Write(a(1))
‘ElseIf Request.Params(a(2)) <> Nothing Then
‘Response.Write(a(2))
End If
End If
Next
‘Controls.Add(radMachines)
‘Dim Str
‘If Page.IsPostBack Then
‘Str = Request.Params(radMachines.Checked.ToString)
‘End If
‘Response.Write(StringResult)
regkey1.Close()
regKey2.Close()
End Sub
End Class