Reputation: 19111
I'm seeing some strange behaviour when making a change to the following VB.net code. This is the original sourcecode:
Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
Dim possiblePurposes As New InfoCollector.Purpose
Dim isPurposeValid As Boolean = False
'Any of the following purposes (but only these)
'should be considered valid
Select Case UCase(purposeId)
Case UCase(possiblePurposes.FirstPurpose), _
UCase(possiblePurposes.SecondPurpose), _
UCase(possiblePurposes.ThirdPurpose), _
UCase(possiblePurposes.FourthPurpose)
isPurposeValid = True
Case Else
isPurposeValid = False
End Select
Return isPurposeValid
End Function
This is the new version. The only change is the addition of a fifth valid purpose:
Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
Dim possiblePurposes As New InfoCollector.Purpose
Dim isPurposeValid As Boolean = False
Select Case UCase(purposeId)
Case UCase(possiblePurposes.FirstPurpose), _
UCase(possiblePurposes.SecondPurpose), _
UCase(possiblePurposes.ThirdPurpose), _
UCase(possiblePurposes.FourthPurpose), _
UCase(possiblePurposes.FifthPurpose)
isPurposeValid = True
Case Else
isPurposeValid = False
End Select
Return isPurposeValid
End Function
I compiled this new version on my local PC and tested the functionality, and it worked fine. After checking this into our central code repository, and building it on the server however, the usage failed (it appeared to be ignoring the new purpose). While trying to figure out what is missing, I decompiled the .DLL found on the server, and this is what it gave me (Note: I've changed the variable names and reformatted slightly):
Private Function ValidateSelectedId(ByVal purposeId As String) As Boolean
Dim ValidateSelectedId As Boolean
Dim possiblePurposes As Purpose = New Purpose()
Dim isPurposeValid As Boolean = False
Dim str As String = Strings.UCase(purposeId)
If (Operators.CompareString(str, Strings.UCase(possiblePurposes.FirstPurpose), False) <> 0) Then
If (Operators.CompareString(str, Strings.UCase(possiblePurposes.SecondPurpose), False) <> 0
AndAlso (Operators.CompareString(str, Strings.UCase(possiblePurposes.ThirdPurpose), False) = 0
OrElse Operators.CompareString(str, Strings.UCase(possiblePurposes.FourthPurpose), False) <> 0)) Then
If (Operators.CompareString(str, Strings.UCase(possiblePurposes.FifthPurpose), False) = 0) Then
Return True
End If
isPurposeValid = False
End If
End If
Return isPurposeValid
End Function
I also tried decompiling this into C#, which might be a little easier to read for some of us:
private bool ValidateSelectedId(string purposeId)
{
bool ValidateSelectedId;
Purpose possiblePurposes = new Purpose();
bool isPurposeValid = false;
string str = Strings.UCase(purposeId);
if (Operators.CompareString(str, Strings.UCase(possiblePurposes.FirstPurpose), false) != 0)
{
if (Operators.CompareString(str, Strings.UCase(possiblePurposes.SecondPurpose), false) != 0
&& (Operators.CompareString(str, Strings.UCase(possiblePurposes.ThirdPurpose), false) == 0
|| Operators.CompareString(str, Strings.UCase(possiblePurposes.FourthPurpose), false) != 0))
{
if (Operators.CompareString(str, Strings.UCase(possiblePurposes.FifthPurpose), false) == 0)
{
return true;
}
isPurposeValid = false;
}
}
return isPurposeValid;
}
This however, seems to be doing something like the inverse of what I wanted, and not at all what the original source code is saying!
I can't see how the original source code could have been compiled to this. Could there be something wrong with my decompiler (I'm using Just Decompile from Telerik)? If so, how come the logic works on my local PC, but not on the server?
Could there actually be some kind of bug in the compile-process? Or am I being a complete Id**t, and simply misunderstanding the logic in the decompiled code?
Any relevant theories to explain this will be greatly appreciated.
Upvotes: 1
Views: 345
Reputation: 19111
Silly me.
I eventually discovered the reason this did not work on the server: There was another related bug which had been fixed locally, but not on the server.
Silly decompiler.
I was confused by the result from the decompiler, which was obviously messed up. I've used JustDecompile many times before, but never run across a problem like this. Apparently, it is unable to decompile the code from the above method in any reasonable fashion.
My assumptions are that some form of optimization is done during compilation, which JustDecompile has trouble understanding and displaying properly.
I just wanted to verify that my changes had been published to the server. Instead I was sent on a wild goose chase for a phantom bug. Lesson learned: Use the decompiler when needed, but do not automatically trust everything it tells you.
Upvotes: 3