处理泛型主题(根据 Shield 4.0),有必要编写一个泛型方法,如果数组包含某个值,该方法将返回布尔值 true。本书继续解释说,由于 T 是泛型类型,为了比较泛型类型的对象,这些对象的类必须实现带有 T 或 IEquatable 参数的 IEquatable 接口。还写到在这些接口中定义了一个比较 Equals() 的方法。这立即导致几个问题:
首先,为什么我们需要实现任何接口来比较泛型类型对象?Equals() 方法是指 Object => 中定义的方法,存在于每个对象中。我意识到为了在这个例子中比较对象,你需要实现上面描述的接口,但我不明白为什么要这样做。
其次,根据 Shield,正如我上面写的,为了比较泛型方法中的对象,建议使用参数 T 或 IEqutable 来实现 Equtable。一个是参数化的,另一个不是。问题是在哪种情况下应该使用哪一个?
此外,在他的书中,Shield 演示了一个检查值是否在数组中的方法示例。这是方法:
public static bool IsIn<T>(T what, T[] obs) where T : IEquatable<T>
{
foreach(T v in obs)
{
if (v.Equals(what))
{
return true;
}
else
{
return false;
}
}
}
这里还有两个问题。
首先,让我先说这种方法行不通。工作室产生编译错误“并非所有方法分支都返回值”。我重新检查了几次编写的代码,但错误仍然存在。如何解决?
其次,我不确定我是否正确理解该方法的签名意味着只有实现 IEquatable 接口的那些类型的对象才能传递给该方法?换句话说,如果我想将一些学生的数组传递给该方法并在其中找到 Vasya Pupkin,那么我的学生类应该是这样的?
class Student<T> : IEquatable<T>
{
public string Name;
public string Surname;
public bool Equals(T other)
{
//some code for compare
return false;
}
}
请按顺序回答所有问题。谢谢
该接口
IEquatable<>旨在避免在比较时对值类型进行不必要的打包。只要每个人都对对象感到满意并且只使用它们,该方法
object.Equals(object)就没有特别的缺点(过度类型转换并不是特别可怕的缺点)。但是当泛型类型出现在语言中时,事情变得更糟了。尝试
object.Equals(object other)在值类型上调用方法会导致:一般来说,泛型类型的发明正是为了避免不必要的结构装箱,所以仅仅为了比较而需要装箱是一场灾难。事实上,
System.Collections.Generics.Dictionary<,>由于不断包装,泛型集合的性能甚至可能比旧变体更差System.Collections.Hashtable。因此,发明了一个新接口,允许您比较两个值而无需类型转换(因此,无需打包)。
现在谈谈你的方法。首先,书中的建议并不完全正确:标准库对这些方法有不同的约定。如果前者不可用
IEquatable<>,您可以使用EqualityComparer<>内部使用IEquatable<>旧方法或旧方法的类,而不需要实现。object.Equals此外,最好有机会将任何实现传递给该方法IEqualityComparer<>(例如,比较字符串而不考虑大小写)。这样会更正确:
(嗯,我已经写过这里方法中的第二个错误:两个分支都在条件运算符中执行 // 数组搜索不起作用)
使用这种方法的实现,它可以像简单的类一样使用(这些类的对象通过引用简单地比较):
以及更高级的:
Equals(object obj)最开始出现在 .NET 中,然后还没有泛型。在 .NET 2.0 中引入泛型之前,Equals(object obj)大多数情况下的方法覆盖看起来像这样:事实证明,在大多数情况下,不同类型的对象不可能相等。为了让生活更轻松,我们提出了一个界面
IEquatable<T>,您可以在其中立即比较 2 个对象,而无需检查它们的类型(这也需要一些时间)。以一种好的方式,现在您应该
IEquatable<T>为所有可以比较的类实现。同时,您不应该忘记重新定义旧Equals版本,以实现兼容性。例如,您可以这样做:关于“不是所有的方法分支都返回值”:如果obs为空,那么里面的代码
foreach永远不会被执行,因此方法不会满足任何return语句。因此错误。据我了解,方法代码应该是这样的:
是的,此方法的签名意味着只有实现 IEquatable 接口的类型的对象才能传递给此方法。