【问题标题】:Use right Equals method when use generic type in C# [duplicate]在 C# 中使用泛型类型时使用正确的 Equals 方法[重复]
【发布时间】:2020-03-25 01:30:54
【问题描述】:

我有课:

public class A : IEquatable<A>
{
  ...
  public bool Equals(A data) { ... }
}

public class B
{
   ...
}

以及自定义作业的通用类

public class CommonFilter<T>
{
   public T GetBy(T data) {
      var item = list.FirstOrDefault(s=> s?.Equals(data) == true);
      ...
   }
}

list 如果List&lt;T&gt; 输入。

CommonFilter<A> cmA = GetFilter();
var result = cmA.GetBy(data);

在调试模式下,如果我有 CommonFilter&lt;A&gt; 这样的对象,我希望在 LINQ 中使用 A 类中的 Equals 方法,但事实并非如此。

如何做到这一点?

【问题讨论】:

  • 您还需要在A 中覆盖Equals(object)
  • 我知道因为我在VS 2019中放了断点,所以没有到达
  • IIRC,EqualityComparer&lt;T&gt;.Equals(s, data) 应该选择正确的Equals
  • 如果没有好的minimal reproducible example,就不可能确定您的代码为什么不起作用。但是,很可能您还没有在您的类型中完全实现平等。有关如何正确执行此操作的详细信息,请参阅标记重复以及 Stack Overflow 上数百个其他与相等相关的问题。如果您在查看所有这些材料后仍然遇到问题,请发布一个新问题,但这次请确保您提供正确的minimal reproducible example,该minimal reproducible example 可以可靠地重现问题,并说明您可以具体做什么'想不通。
  • 此外,您的调用站点可能根本无法访问完整的类型信息,因此调用了错误的Equals() 方法。如果您正确实现了相等性,这将不是问题(因为object.Equals() 方法与接口方法一样有效,尽管有装箱开销),但如果您正确声明约束,您可以摆脱它。查看该特定问题的其他标记重复项。

标签: c#


【解决方案1】:

正如 Jasper 指出的那样,您缺少通用约束:

public class CommonFilter<T> where T : IEquatable<T>

其他答案中没有解释的是为什么需要它。

请记住,编译器需要在编译时解析调用s?.Equals(data)。在您的代码中,编译器对T 一无所知,因此将调用解析为任何T 的唯一可能候选者:object.Equals,默认为引用比较。

另一方面,如果您定义了约束,那么编译器知道任何给定的T 必须实现更具体的IEquatable&lt;T&gt;.Equals,并将解析对该方法的调用。 p>

如果定义约束是一项重大更改,或者您根本无法实现它,因为您还需要处理引用相等性合适的数据,那么您可以在 GetBy 内部分支以判断 T 是否实现 IEquatable&lt;T&gt; , 对泛型类型进行类型检查通常是一个危险信号,但在这种特定情况下它可能是合理的。

如果可能,我更喜欢第一个选项,因为这样您就明确禁止将 GetBy 与未实现 IEquatable&lt;T&gt; 的类型一起使用。

【讨论】:

  • 总是喜欢这样的答案。解释 为什么what 一样重要,甚至更重要。
【解决方案2】:

我认为你需要:

public class CommonFilter<T> where T : IEquatable<T>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 2013-11-09
    • 1970-01-01
    相关资源
    最近更新 更多