Take the 2-minute tour ×

I'm using LINQ expressions to dynamically search for values in a collection and I've come across a strange issue that seems to be caused by searching for a string that is the result of a String.Format() operation.

Here is a simplified version of what I am trying to do, since in practice I do not actually know what type of value I am searching for, I have to treat everything as an Object.

Dim stringToFind As String = "Some Special Value"

' Create a collection of 10 strings, one of which being the string to find '
Dim myStrings As New List(Of Object)
For i As Integer = 0 To 9
    If (i = 3) Then
        myStrings.Add("Boring Plain Old Value")
    End If

' Create the predicate for <Function(x) x = stringToFind> '
Dim left = Expression.Parameter(GetType(Object), "x")
Dim right = Expression.Constant(stringToFind)
Dim eq = Expression.Equal(left, right)
Dim predicate = Expression.Lambda(Of Func(Of Object, Boolean))(eq, left).Compile()

' Compare the results '
Dim standardResults = myStrings.Where(Function(x) x = stringToFind)
Dim expressionResults = myStrings.Where(predicate)

' Expected Output:'
' Standard Method: 1 '
' LINQ Expressions: 1 '
Console.WriteLine(String.Format("Standard Method: {0}", standardResults.Count()))
Console.WriteLine(String.Format("LINQ Expressions: {0}", expressionResults.Count()))

What happens here is that the standard method correctly returns 1 result, while the LINQ Expressions method returns 0. However, if the special value is added to the collection without using String.Format() (myStrings.Add(stringToFind)) then the expression returns the correct result as well.

Is there something that String.Format() does to change the encoding of the string, or anything that would effect how a constant expression is created for the string value? Is there another way I could compare two values using LINQ expressions that would get me around this limitation?

share|improve this question
Every string is the same. It does not magically get altered by String.Format(). –  usr Jul 12 '12 at 16:16
add comment

1 Answer

up vote 1 down vote accepted

The VB.NET equality operator does not do a reference comparison. Roughly speaking, it uses the object.Equals method (in contrast to object.ReferenceEquals). Expression trees use object reference equality.

Using string.Format does not do anything special. (There are no "special" strings).

share|improve this answer
Maybe not, but there obviously has to be some difference between String.Format(stringToFind) and stringToFind, otherwise both scenarios would produce the same result. Are you saying that String.Format(stringToFind) generates a new instance of a string so that the ExpressionEquals evaluates to false? –  Mike C Jul 12 '12 at 17:07
@MikeC, yes exactly. The new instance of this particular string reference-compares as false. –  usr Jul 12 '12 at 17:19
Thanks, I was able to use an overload to Expression.Call to specify using the Object.Equals method instead of Object.ReferenceEquals - Expression.Equal(left, right, False, GetType(Object).GetMethod("Equals", {GetType(Object), GetType(Object)})) and that did the trick! –  Mike C Jul 12 '12 at 19:07
add comment

Your Answer


