[英]Regarding Contains and Equals in C#
新手来了我在 Microsoft 文档中阅读了以下代码。 您可以在此处查看网页: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.find?view=net-6.0
public class Part : IEquatable<Part>
{
public string PartName { get; set; }
public int PartId { get; set; }
//other code
public override bool Equals(object obj)
{
if (obj == null) return false;
Part objAsPart = obj as Part;
if (objAsPart == null) return false;
else return Equals(objAsPart);
}
// other code
public bool Equals(Part other)
{
if (other == null) return false;
return (this.PartId.Equals(other.PartId));
}
}
public class Example
{
public static void Main()
{
// Create a list of parts.
List<Part> parts = new List<Part>();
// Add parts to the list.
parts.Add(new Part() { PartName = "crank arm", PartId = 1234 });
parts.Add(new Part() { PartName = "chain ring", PartId = 1334 });
parts.Add(new Part() { PartName = "regular seat", PartId = 1434 });
parts.Add(new Part() { PartName = "banana seat", PartId = 1444 });
parts.Add(new Part() { PartName = "cassette", PartId = 1534 });
parts.Add(new Part() { PartName = "shift lever", PartId = 1634 }); ;
//other code
// Check the list for part #1734. This calls the IEquatable.Equals method
// of the Part class, which checks the PartId for equality.
Console.WriteLine("\nContains: Part with Id=1734: {0}",
parts.Contains(new Part { PartId = 1734, PartName = "" }));
}
}
现在,我的问题是关于parts.Contains(new Part { PartId = 1734, PartName = "" })
行。 这是ListT.Contains(T)
方法。
正如您从 Microsoft 参考源(此处: https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,521b9f7129105e15 )中看到的, Contains
方法的代码如下:
public bool Contains(T item) {
if ((Object) item == null) {
for(int i=0; i<_size; i++)
if ((Object) _items[i] == null)
return true;
return false;
}
else {
EqualityComparer<T> c = EqualityComparer<T>.Default;
for(int i=0; i<_size; i++) {
if (c.Equals(_items[i], item)) return true;
}
return false;
}
}
所以你可以看到Contains
方法使用Equals
方法,但是哪个Equals
呢? c.Equals(_items[i], item)
表示我们调用的方法属于EqualityComparer<T>.Default
。 实际上, Default
是EqualityComparer<T>
class 的属性,它返回相同 class 的 object。 所以我们这里看到的Equals
应该属于EqualityComparer<T>
class。
问题 #1:我们如何拥有EqualityComparer<T>
class 的 object,因为这个 class 是抽象的?
问题 #2:我们如何调用c.Equals(_items[i], item)
因为这个方法也是抽象的? (如您所见: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.equalitycomparer-1.equals?view=net-6.0
But the most important of all, Question #3: How do we go from c.Equals(_items[i], item)
method of class EqualityComparer<T>
, to the IEquatable.Equals
method which is implemented in the Part
class. 第一种方法会调用第二种方法吗?
“
Default
属性检查类型T
是否实现了System.IEquatable<T>
泛型接口,如果是,则返回调用IEquatableT.Equals
方法实现的EqualityComparer<T>
。否则,它返回EqualityComparer<T>
,由T
提供。”
我不明白如何调用第二种方法IEquatable.Equals
。
我很抱歉发了这么长的帖子。 提前致谢!
我们怎么能有一个
EqualityComparer<T>
class 的 object 因为这个 class 是抽象的?
你没有,你有一个在EqualityComparer<T>.CreateComparer
方法中创建的 EqualityComparer<T EqualityComparer<T>
继承者的实例。
问题 #2:我们如何调用
c.Equals(_items[i], item)
因为这个方法也是抽象的?
导致EqualityComparer<T>
的具体继承者应该并实现此方法(阅读有关abstract
keyword 的文档)。 文档中稍作修改的示例可能会澄清一些事情:
// create an instance of Square and save to variable of Square type:
Square square = new Square(12);
// assign Square to variable of Shape type, works cause Square is Shape:
Shape shape = square;
// access the abstract method declared on Shape and implemented by Square:
Console.WriteLine($"Area of the square = {shape.GetArea()}");
abstract class Shape
{
public abstract int GetArea();
}
class Square : Shape
{
private int _side;
public Square(int n) => _side = n;
// GetArea method is required to avoid a compile-time error.
public override int GetArea() => _side * _side;
}
Question #3: How do we go from
c.Equals(_items[i], item)
method of classEqualityComparer<T>
, to theIEquatable.Equals
method which is implemented in the Part class. 第一种方法会调用第二种方法吗?
因为已经提到的CreateComparer
方法检查泛型类型T
是否实现了这个接口,如果它实现了 - 使用Default
实例中的实现:
// If T implements IEquatable<T> return a GenericEqualityComparer<T>
if (typeof(IEquatable<T>).IsAssignableFrom(t)) {
return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer<int>), t);
}
一些额外的注意事项:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.