[英]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.