7

I have the following code to create a static list of elements and retrieve them by Id:

Private Shared Property SubStructTypes As IList(Of SubstructureType)

Shared Sub New()
    SubStructTypes = New List(Of SubstructureType) From {
        New SubstructureType With {.Id = "PURLIN", .Description = "Purlin"},
        New SubstructureType With {.Id = "METALDECKING", .Description = "Metal Decking"},
        New SubstructureType With {.Id = "WOODDECKING", .Description = "Wood Decking"}
    }
End Sub

Public Shared Function GetById(ByVal myId As String) As SubstructureType
    If String.IsNullOrWhiteSpace(myId) Then
        Return Nothing
    End If

    Dim straightCompare = SubStructTypes.SingleOrDefault(Function(subStruct) subStruct.Id = myId)
    Dim howIsThisFindingAnything = SubStructTypes.SingleOrDefault(Function(subStruct) subStruct.Id.ToUpper() = myId.ToLower())

    Return SubStructTypes.SingleOrDefault(Function(subStruct) subStruct.Id.ToLower() = myId.ToLower())
End Function

There's nothing special about the class:

<Serializable>
Public Class SubstructureType
    Public Property Id As String
    Public Property Description As String
End Class

When passing in an Id, the SingleOrDefault method will find the value in the list regardless of the string casing. This is seen in the screenshot below: enter image description here

Question: Why is calling SingleOrDefault on my collection to filter off an Id value finding the element in the list, even though the casing is different (i.e. "Purlin" vs "PURLIN"). This is clearly seen in my howIsThisFindingAnything variable where I explicitly change the casing.

Note:

  • SingleOrDefault is using the standard .NET call
  • Framework version: .NET 4
contactmatt
  • 18,116
  • 40
  • 128
  • 186
  • Are you using linq to entities? http://stackoverflow.com/questions/3843060/linq-to-entities-case-sensitive-comparison – DLeh Mar 18 '14 at 16:53
  • @Dleh No, just an in-memory query on a static list. – contactmatt Mar 18 '14 at 16:54
  • maybe you should try using String.Equals() instead of the = sign? I'm not as familiar with how VB interprets = – DLeh Mar 18 '14 at 16:57
  • 1
    or maybe compare: http://stackoverflow.com/questions/900927/comparing-strings-in-vb – DLeh Mar 18 '14 at 16:59
  • @DLeh You're right, that worked. By default, does VB.NET not care about case sensitivity? To test this, I added a variable Dim isTrue = "test" = "TEST" and the expression was true. – contactmatt Mar 18 '14 at 17:11
  • When I run this and pass in "Purlin" as the id, `howIsThisFindingAnything` is Nothing meaning it didn't find anything. Your return statement's filter is changing both to lower case when doing comparison, so that's ignoring any case differences. – CoderDennis Mar 18 '14 at 17:19
  • @contactmatt That expression is false when I run it. I don't think I've got anything other than the default settings for VB.NET. – CoderDennis Mar 18 '14 at 17:29

2 Answers2

7

In VB.Net there is the statement/project compilation option: Option Compare.

There are two options for this: Text and Binary.

Its probably that you have this configured somewhere to Text.

Depending on how your environment is setup will dictate how this is set by default. Checking my setups, I usually have it defaulted to binary in the project settings.

The difference is (from MSDN here):

Binary:

Results in string comparisons based on a sort order derived from the internal binary representations of the characters. This type of comparison is useful especially if the strings can contain characters that are not to be interpreted as text. In this case, you do not want to bias comparisons with alphabetical equivalences, such as case insensitivity.

Text:

Results in string comparisons based on a case-insensitive text sort order determined by your system's locale. This type of comparison is useful if your strings contain all text characters, and you want to compare them taking into account alphabetic equivalences such as case insensitivity and closely related letters. For example, you might want to consider A and a to be equal, and Ä and ä to come before B and b.

These options have effects not just on the obvious equality scenario, but also areas such as sort ordering.

This can be set/defaulted in the following locations:

  1. The very top of a code file
  2. Project default set in the Project Properties >> Compile page
  3. Default for new projects set in the Options >> Projects and Solutions >> VB Defaults page.

Personally I would tend to use Binary as it behaves most similarly to other languages such as C#/Javascript and so on, and then explicitly code for where I needed a case-insensitive equality.

Jon Egerton
  • 40,401
  • 11
  • 97
  • 129
0

According to comment thread, the answer to this was to use String.Compare instead of =

See this thread for more comparing strings in vb

Community
  • 1
  • 1
DLeh
  • 23,806
  • 16
  • 84
  • 128
  • 2
    I deleted my answer, you were there first. ;) +1 – Crono Mar 18 '14 at 17:18
  • @Crono very respectable – contactmatt Mar 18 '14 at 17:21
  • @CoderDennis that answer tells you how to change your environment to fix the issue, this answer tells you how to fix it in the given environment. – DLeh Mar 18 '14 at 17:39
  • @CoderDennis please keep downvotes for answers that are actually incorrect. The fact that it's a workaround might be worth a comment, but *not* a downvote. – Crono Mar 19 '14 at 15:24