簡體   English   中英

關於 C# 中的包含和等於

[英]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 實際上, DefaultEqualityComparer<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. 第一種方法會調用第二種方法嗎?

這里: https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.equalitycomparer-1?view=net-6.0它說如下:

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 class EqualityComparer<T> , to the IEquatable.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);
}

一些額外的注意事項:

  • 為了更好地理解這是如何工作的,您可能需要閱讀有關 generics 的信息: 此處此處此處的一些重要信息
  • referencesource.microsoft.com is for the older .NET Framework sources, if you are working with modern .NET Core (including .NET 5, .NET 6 and upcoming .NET 7) you can use source.dot.net

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM