none
List Contains的疑問 RRS feed

  • 問題

  • 發現到一個關於List.Contains的小問題,

    為了簡單說明我的問題,麻煩各位前輩看一下下面程式碼。

    程式碼:

    string[] ArrayA0 = new string[] { "111", "222" };
    string[] ArrayA1 = new string[] { "111", "222" };
    string[] ArrayB = new string[] { "111", "333" };
    string[] ArrayC = new string[] { "111", "444" };
    
    List<string[]> ListA0B = new List<string[]>(0);
    ListA0B.Add(ArrayA0);
    ListA0B.Add(ArrayB);
    
    List<string[]> ListA1B = new List<string[]>(0);
    ListA1B.Add(ArrayA1);
    ListA1B.Add(ArrayB);
    
    List<string[]> ListA0C = new List<string[]>(0);
    ListA0C.Add(ArrayA0);
    ListA0C.Add(ArrayC);
                
    Console.WriteLine("A0B+A0C");
    for (int i = 0; i < ListA0C.Count; i++)
    {
        bool Is_Exist = ListA0B.Contains(ListA0C[i]);
        Console.WriteLine("{0} {1}", i, Is_Exist);
    }
    
    Console.WriteLine("A1B+A0C");
    for (int i = 0; i < ListA0C.Count; i++)
    {
        bool Is_Exist = ListA1B.Contains(ListA0C[i]);
        Console.WriteLine("{0} {1}", i, Is_Exist);
     }

    輸出結果:

    A0B+A0C
    0 True
    1 False
    
    A1B+A0C
    0 False
    1 False

    問題1.

    明明A0與A1都是一樣的,

    為什麼contians的結果卻是不一樣?

    問題2.

    如果要將 第一個contians(A0B+A0C) 與 第二個contians(A1B+A0C) 結果變成

    0 true, 1 false 請問還有哪些方法?除了要針對每個陣列的每個元素比較之外。

    ===我叫分隔線===

    我剛開始以為contains是針對內容來做比較,

    可是後來發現程式錯誤,測試了一下才發現好像不是,

    就算字串陣列的值都一樣,但是contains的結果卻不一樣,

    這讓我蠻驚訝的。

    麻煩各位前輩指點一下,謝謝^^


    • 已編輯 笨嘎嘎 2013年12月12日 上午 04:05
    2013年12月12日 上午 04:04

解答

    • 已標示為解答 笨嘎嘎 2013年12月12日 上午 07:38
    2013年12月12日 上午 05:12
  • A0與A1是內容值一樣, 但是A0和A1是不同的物件參考變數, 參考的也是不同的物件

    • 已標示為解答 笨嘎嘎 2013年12月12日 上午 07:38
    2013年12月12日 上午 07:11
  • (1) 陣列是一種參考型別

    (2) A0 和 A1 兩個陣列變數是指向兩個不同的實體 (執行個體)

    (3) List<T>.Contains() 方法的內部是使用 EqualityComparer<T>.Equals 方法來做比較, 這方法又來自於該 T 型別的 Equals 方法, 若是該 T 型別有實做 IEquatable<T>.Equals 方法, 則優先採用此方法,若無, 則使用 繼承(有可能會覆寫) 自上層的 Equals 方法 (最上端就是 Object.Equals() )

    (4) 在陣列型別的例子中, 它採用的就是繼承自Object.Equals 方法, 而這個方法的內容是比較實體, 既然 A0, A1 是不同實體, 自然答案是 false


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 笨嘎嘎 2013年12月12日 上午 07:38
    2013年12月12日 上午 07:23
    版主

所有回覆

    • 已標示為解答 笨嘎嘎 2013年12月12日 上午 07:38
    2013年12月12日 上午 05:12
  • 感謝亂馬客前輩的回答,

    我將程式修改後還是一樣的結果。

    程式碼:

    string[] ArrayA0 = new string[] { "111", "222" };
    string[] ArrayA1 = new string[] { "111", "222" };
    string[] ArrayB = new string[] { "111", "333" };
    string[] ArrayC = new string[] { "111", "444" };
    
    List<string[]> ListA0B = new List<string[]>(0);
    ListA0B.Add(ArrayA0);
    ListA0B.Add(ArrayB);
    
    List<string[]> ListA1B = new List<string[]>(0);
    ListA1B.Add(ArrayA1);
    ListA1B.Add(ArrayB);
    
    List<string[]> ListA0C = new List<string[]>(0);
    ListA0C.Add(ArrayA0);
    ListA0C.Add(ArrayC);
    
    Console.WriteLine("A0B+A0C");
    for (int i = 0; i < ListA0C.Count; i++)
    {
        bool Is_Exist = false;
        for (int j = 0; j < ListA0B.Count; j++)
        {
            bool Is_Equal = ListA0B[j].Equals(ListA0C[i]);
            //bool Is_Equal = object.Equals(ListA0B[j], ListA0C[i]);
            //bool Is_Equal = Object.Equals(ListA0B[j], ListA0C[i]);
            //bool Is_Equal = Array.Equals(ListA0B[j], ListA0C[i]);
            if (Is_Equal)
            {
                Is_Exist = true;
                break;
            }
                        
        }
        Console.WriteLine("{0} {1}", i, Is_Exist);
    }
    
    Console.WriteLine("A1B+A0C");
    for (int i = 0; i < ListA0C.Count; i++)
    {
        bool Is_Exist = false;
        for (int j = 0; j < ListA1B.Count; j++)
        {
            bool Is_Equal = ListA1B[j].Equals(ListA0C[i]);
            //bool Is_Equal = object.Equals(ListA1B[j], ListA0C[i]);
            //bool Is_Equal = Object.Equals(ListA1B[j], ListA0C[i]);
            //bool Is_Equal = Array.Equals(ListA1B[j], ListA0C[i]);
            if (Is_Equal)
            {
                Is_Exist = true;
                break;
            }
                        
        }
        Console.WriteLine("{0} {1}", i, Is_Exist);
    }

    結果:

    A0B+A0C
    0 True
    1 False
    
    A1B+A0C
    0 False
    1 False


    明明A0與A1的值都一樣,

    但是不管我用object.Equals, Object.Equals, Array.Equals出來就是false,

    就算我不用List,直接拿ArrayA0, ArrayA1來做Equals也都是false。

    亂馬克前輩所提供的網址內,MSDN有段話:

    「範例的輸出所示, person1a 和 person1b 相等,因為它們參考相同的物件。不過, person1a 和 person2 不相等,不過,它們具有相同的值。」

    如果說contains也是這樣子的話我就完全明瞭了。

    用舉例來說的話,

    小名跟小明是同卵雙胞胎,雖然DNA一樣,但是是不同人。

    object.Equals(小名, 小明) = false。不同人

    那請問,如果要看兩個陣列內的元素(兩個人的DNA)是否相同,

    就一定要自己寫比較嗎?

    請問是否有更聰明的辦法?

    PS:

    有看到使用Bitconvert.toString(byte_array),但是不適用在這裡~"~


    • 已編輯 笨嘎嘎 2013年12月12日 上午 07:16
    2013年12月12日 上午 07:06
  • A0與A1是內容值一樣, 但是A0和A1是不同的物件參考變數, 參考的也是不同的物件

    • 已標示為解答 笨嘎嘎 2013年12月12日 上午 07:38
    2013年12月12日 上午 07:11
  • (1) 陣列是一種參考型別

    (2) A0 和 A1 兩個陣列變數是指向兩個不同的實體 (執行個體)

    (3) List<T>.Contains() 方法的內部是使用 EqualityComparer<T>.Equals 方法來做比較, 這方法又來自於該 T 型別的 Equals 方法, 若是該 T 型別有實做 IEquatable<T>.Equals 方法, 則優先採用此方法,若無, 則使用 繼承(有可能會覆寫) 自上層的 Equals 方法 (最上端就是 Object.Equals() )

    (4) 在陣列型別的例子中, 它採用的就是繼承自Object.Equals 方法, 而這個方法的內容是比較實體, 既然 A0, A1 是不同實體, 自然答案是 false


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 笨嘎嘎 2013年12月12日 上午 07:38
    2013年12月12日 上午 07:23
    版主
  • 沒人幫你做好輪子, 你就得自己做.

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2013年12月12日 上午 08:03
    版主