Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VB.NET LINQ query disregarding string casing

Tags:

.net

vb.net

linq

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
like image 578
contactmatt Avatar asked Mar 18 '14 16:03

contactmatt


1 Answers

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.

like image 179
Jon Egerton Avatar answered Oct 01 '22 23:10

Jon Egerton