Сравнение строк с использованием выражений LINQ и String.Format

Я использую выражения LINQ для динамического поиска значений в коллекции и столкнулся со странной проблемой, которая, похоже, вызвана поиском строки, являющейся результатом операции String.Format().

Вот упрощенная версия того, что я пытаюсь сделать, поскольку на практике я фактически не знаю, какой тип значения ищу, я должен рассматривать все как 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(String.Format(stringToFind))
    Else
        myStrings.Add("Boring Plain Old Value")
    End If
Next

' 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()))
Console.ReadLine()

Здесь происходит то, что стандартный метод правильно возвращает 1 результат, а метод LINQ Expressions возвращает 0. Однако, если специальное значение добавлено в коллекцию без использования String.Format () (myStrings.Add(stringToFind)), тогда выражение вернет правильный результат как Что ж.

Есть ли что-то, что String.Format () делает для изменения кодировки строки, или что-нибудь, что может повлиять на то, как создается постоянное выражение для значения строки? Есть ли другой способ сравнить два значения с помощью выражений LINQ, который помог бы мне обойти это ограничение?


person mclark1129    schedule 12.07.2012    source источник
comment
Каждая струна одинакова. String.Format () не меняет его волшебным образом.   -  person usr    schedule 12.07.2012


Ответы (1)


Оператор равенства VB.NET не выполняет сравнение ссылок. Грубо говоря, он использует метод object.Equals (в отличие от object.ReferenceEquals). Деревья выражений используют равенство ссылок на объекты.

Использование string.Format ничего особенного не делает. (Нет никаких "особых" строк).

person usr    schedule 12.07.2012
comment
Возможно, нет, но, очевидно, должна быть какая-то разница между String.Format (stringToFind) и stringToFind, иначе оба сценария дадут один и тот же результат. Вы говорите, что String.Format (stringToFind) генерирует новый экземпляр строки, так что ExpressionEquals оценивается как false? - person mclark1129; 12.07.2012
comment
@MikeC, да, именно так. Новый экземпляр этой конкретной строковой ссылки сравнивается как ложь. - person usr; 12.07.2012
comment
Спасибо, мне удалось использовать перегрузку для Expression.Call, чтобы указать использование метода Object.Equals вместо Object.ReferenceEquals - Expression.Equal (left, right, False, GetType (Object) .GetMethod (Equals, {GetType (Object) ), GetType (Object)})) и это помогло! - person mclark1129; 12.07.2012