1
var list = new List<string>();
var word = "some word";
list.Add("some word");
list.Add("some sentence");
list.Add(word);

I know Equals compare the value stored in the reference while "==" compares whether two references point to the same object. But is it the same even in lambda expressions?

list.RemoveAll(x => x.Equals("some word"));
list.RemoveAll(x => x == "some word");

Do these statements produces same result?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Praburaj
  • 613
  • 8
  • 21
  • LINQ does not change how the `==` operator or `Equals` method work. Also, `==` does not necessarily "compare the reference" in C# as it does in Java - it is whatever sensible operator overload has been created. One difference that can bite fairly easily is `null.Equals(x)` will throw an exception whereas `null == x` will not. – user2864740 Jan 05 '17 at 07:12
  • 2
    ""==" compares the reference itself" - that depends on the type of `x`. If `x` is a string, it's going to call the `==` operator in `string`, which performs a value comparison. If the type of `x` is object (compile-time type, that is) then it will perform a reference comparison. – Jon Skeet Jan 05 '17 at 07:14
  • 2
    Please provide a [mcve] so we can actually reason about the meaning of `==`. Ideally, tell us the motivation for the question, too... fundamentally, code in lambda expressions behaves as normal, assuming it's being converted to a delegate. (If it's being converted to an expression tree then the meaning should be the same, but it could be *interpreted* differently by whatever is consuming the tree.) – Jon Skeet Jan 05 '17 at 07:14
  • `.Equals` does not "compare the value stored in the reference", it does whatever the programmer of `T.Equals(T)` decided it should do, and in the context of strings it does a string *value* comparison, not a reference comparison, though surely two equal references means equal values as well, but even with different references, but the same value, `.Equals` on string will return `true`. – Lasse V. Karlsen Jan 05 '17 at 07:19
  • @Lasse V.Karlsen Yeah I agree that. I wanted to know incase of String objects alone. – Praburaj Jan 05 '17 at 07:21
  • I’m closing this question after all since the discussion and the edits to the question have made it move from being about the lambda expressions more towards the confusion between the equals operator and the `Equals` method (particularly for strings). – poke Jan 05 '17 at 07:32
  • @poke: I don't know - it still looks like it's more about lambda expressions, to me. But I agree it's not terribly clear. – Jon Skeet Jan 05 '17 at 08:02

2 Answers2

6

I know Equals compare the value stored in the reference while "==" compares whether two references point to the same object.

No, that's just the behaviour of the default == operator for reference types. When both sides of == have a compile-time type of string, the bool operator==(string, string) overload declared in the string class is used, and you get the same result as Equals, when the target of the call isn't null.

That behaviour is exactly the same in regular code as in lambda expressions. Code written in a lambda expression should behave exactly the same way as code written not in a lambda expression... although if the lambda expression is converted to an expression tree, the compiler only emits the code as data, so it's up to whatever's consuming the expression tree to do the right thing with it.

So yes, the code should work absolutely fine - the only difference between using Equals and using == is that if you list contains any null elements, the x.Equals(...) call will throw a NullReferenceException. Personally I usually compare strings with == just for simplicity.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I agree with your answer if the program is written in c#.But in Java there is no operator overloading how does it behave in that case? – Praburaj Jan 05 '17 at 07:27
  • 3
    @Prabu: Then it will obey the rules of Java instead. There's no point asking a question about one specific language and then assuming the results will apply to every other language. – Jon Skeet Jan 05 '17 at 07:31
3

But is it the same even in lambda expressions?

There is a simple way to answer that: Test it!

void Main()
{
    WhatIsThis<string>(x => x.Equals("foo"));
    Console.WriteLine();
    WhatIsThis<string>(x => x == "foo");
}

void WhatIsThis<T>(Expression<Func<T, bool>> expr)
{
    Console.WriteLine(expr.Body.NodeType);
    if (expr.Body is MethodCallExpression)
    {
        var ce = expr.Body as MethodCallExpression;
        Console.WriteLine(ce.Method.Name);
        Console.WriteLine(ce.Object.ToString());
        Console.WriteLine(string.Join(", ", ce.Arguments.Select(x => x.ToString())));
    }
    else if (expr.Body is BinaryExpression)
    {
        var be = expr.Body as BinaryExpression;
        Console.WriteLine(be.Method.ToString());
        Console.WriteLine(be.Left.ToString());
        Console.WriteLine(be.Right.ToString());
    }
}

This produces the following output:

Call
Equals
x
"foo"

Equal
Boolean op_Equality(System.String, System.String)
x
"foo"

So, the answer is no. Even in lambda expressions, the difference between the == operator and the Equals method call is maintained. And if you think about it: Why shouldn’t it be the case? It makes no sense for lambda expressions to assume that they would do the same thing here and just simplify it to one or another type. After all, there is a difference.

Community
  • 1
  • 1
poke
  • 369,085
  • 72
  • 557
  • 602