【问题标题】:Linq Lambda expression == and Equals operator [duplicate]Linq Lambda表达式==和Equals运算符[重复]
【发布时间】:2017-01-05 07:11:57
【问题描述】:
var list = new List<string>();
var word = "some word";
list.Add("some word");
list.Add("some sentence");
list.Add(word);

我知道 Equals 比较存储在引用中的值,而 "==" 比较两个引用是否指向同一个对象。但即使在 lambda 表达式中也一样吗?

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

这些语句产生相同的结果吗?

【问题讨论】:

  • LINQ 不会改变 == 运算符或 Equals 方法的工作方式。此外,== 在 C# 中不一定像在 Java 中那样“比较引用” - 它是创建了任何明智的运算符重载。一个很容易咬人的区别是null.Equals(x) 会抛出异常,而null == x 不会。
  • ""==" 比较引用本身" - 这取决于 x 的类型。如果x 是一个字符串,它将调用string 中的== 运算符,它执行一个值比较。如果x的类型是object(即编译时类型),那么它将进行引用比较。
  • 请提供minimal reproducible example,以便我们真正推断== 的含义。理想情况下,也请告诉我们这个问题的动机......从根本上说,lambda 表达式中的代码行为正常,假设它被转换为委托。 (如果它被转换为表达式树,那么含义应该是相同的,但它可能会被任何消耗树的东西解释不同。)
  • .Equals 不会“比较存储在引用中的值”,它会做任何T.Equals(T) 的程序员决定它应该做的事情,并且在字符串的上下文中它会做一个字符串 value 比较,不是引用比较,虽然肯定两个相等的引用也意味着相等的值,但是即使引用不同,但值相同,字符串上的.Equals 将返回true
  • @Lasse V.Karlsen 是的,我同意这一点。我想单独了解 String 对象的情况。

标签: c# .net lambda


【解决方案1】:

我知道 Equals 比较存储在引用中的值,而“==”比较两个引用是否指向同一个对象。

不,这只是引用类型的 默认 == 运算符的行为。当==的两边都有string的编译时类型时,使用string类中声明的bool operator==(string, string)重载,你得到的结果和Equals一样,当调用的目标不为空。

常规代码中的行为与 lambda 表达式中的行为完全相同。用 lambda 表达式编写的代码应该与用 lambda 表达式编写的代码完全相同。not...尽管如果 lambda 表达式转换为表达式树,编译器只会将代码作为数据发出,所以这取决于使用表达式树的任何东西来做正确的事情。

所以是的,代码应该可以正常工作 - 使用 Equals 和使用 == 之间的唯一区别是,如果您列出包含任何 null 元素,x.Equals(...) 调用将抛出 NullReferenceException。就我个人而言,为了简单起见,我通常将字符串与== 进行比较。

【讨论】:

  • 如果程序是用 c# 编写的,我同意你的回答。但是在 Java 中没有运算符重载,在这种情况下它的行为如何?
  • @Prabu:那么它就会遵守 Java 的规则。问一个关于一种特定语言的问题,然后假设结果将适用于所有其他语言是没有意义的。
【解决方案2】:

但是即使在 lambda 表达式中也是一样的吗?

有一个简单的方法来回答这个问题:测试它!

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());
    }
}

这会产生以下输出:

Call
Equals
x
"foo"

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

所以,答案是否定的。即使在 lambda 表达式中,== 运算符和 Equals 方法调用之间的区别也得以保留。如果你想一想:为什么不应该这样呢? lambda 表达式假设它们会在这里做同样的事情并将其简化为一种或另一种类型是没有意义的。毕竟,there is a difference

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多