Listについて<br>のExistsとContainsの違い

22133 ワード

転載:http://www.cnblogs.com/jicheng1014/archive/2010/02/01/1660967.html
 
 
今日は小さなプロジェクトをするとき、リストの中のオブジェクトが存在したかどうかを比較する必要があります.
比較するオブジェクトは新規作成(逆シーケンス化)
Containsを使って比較していると、
問題に気づいた.
以下はテストコードです
[TestMethod()]
public void RemoveDiscendantPowerTest() {
    Power Parent = new Power
    {
        Alias = "testRoot",
        CanDelete = false,
        Description = "     ",
        id = 100,
        PowerName = "     ",
        Childs = new List<Power>
        {
            new Power{
                Alias = "testBranch1",
                CanDelete = true,
                Description = "    1",
                id = 100100,
                PowerName = "    1",
                Childs = new List<Power>{
                    new Power{
                     Alias = "leaf1",
                     CanDelete = true,
                     Description = "    1",
                     id = 100100100,
                     PowerName = "    1"
                    },
                    new Power{
                     Alias = "leaf2",
                     CanDelete = true,
                     Description = "    2",
                     id = 100100101,
                     PowerName = "    2"
                    }
                }
            },
            new Power{
                Alias ="testBranch2",
                CanDelete = true,
                Description = "    2",
                id = 100101,
                PowerName = "    2",
                Childs = new List<Power>{
                    new Power{
                     Alias = "leaf3",
                     CanDelete = true,
                     Description = "    3",
                     id = 100101100,
                     PowerName = "    3"
                    },
                    new Power{
                     Alias = "leaf4",
                     CanDelete = true,
                     Description = "    4",
                     id = 100101101,
                     PowerName = "    4"
                    }
                }
                
            }
        }
    }; // TODO:         
    Power Discendant = new Power{
                     Alias = "leaf4",
                     CanDelete = true,
                     Description = "    4",
                     id = 100101101,
                     PowerName = "    4"
                    };
    // TODO:         
 
 
    Assert.IsTrue(Parent.Childs[1].Childs.Contains(Discendant), "    ,Contains     ");
 
 
 
 
}

 
 
テスト結果は次のとおりです.
image
結論として,新規そっくりのオブジェクトがContainsで返されたfalseは,テストに合格できなかった.
なぜこのような問題が発生したのでしょうか.
答えは簡単です:Containsは記憶されているメモリアドレスが同じかどうかを比較して、値が同じではありません.
テストを変更すると、問題が見つかります.
/// <summary>
///RemoveDiscendantPower    
///</summary>
[TestMethod()]
public void RemoveDiscendantPowerTest() {
    Power Parent = new Power
    {
        Alias = "testRoot",
        CanDelete = false,
        Description = "     ",
        id = 100,
        PowerName = "     ",
        Childs = new List<Power>
        {
            new Power{
                Alias = "testBranch1",
                CanDelete = true,
                Description = "    1",
                id = 100100,
                PowerName = "    1",
                Childs = new List<Power>{
                    new Power{
                     Alias = "leaf1",
                     CanDelete = true,
                     Description = "    1",
                     id = 100100100,
                     PowerName = "    1"
                    },
                    new Power{
                     Alias = "leaf2",
                     CanDelete = true,
                     Description = "    2",
                     id = 100100101,
                     PowerName = "    2"
                    }
                }
            },
            new Power{
                Alias ="testBranch2",
                CanDelete = true,
                Description = "    2",
                id = 100101,
                PowerName = "    2",
                Childs = new List<Power>{
                    new Power{
                     Alias = "leaf3",
                     CanDelete = true,
                     Description = "    3",
                     id = 100101100,
                     PowerName = "    3"
                    },
                    new Power{
                     Alias = "leaf4",
                     CanDelete = true,
                     Description = "    4",
                     id = 100101101,
                     PowerName = "    4"
                    }
                }
                
            }
        }
    }; // TODO:         
    Power Discendant = new Power{
                     Alias = "leaf4",
                     CanDelete = true,
                     Description = "    4",
                     id = 100101101,
                     PowerName = "    4"
                    };
    // TODO:         
 
 
    //Assert.IsTrue(Parent.Childs[1].Childs.Contains(Discendant), "    ,Contains    ");
 
 
 
    Power test = Parent.Childs[1].Childs[1];
 
    Assert.IsTrue(Parent.Childs[1].Childs.Contains(test), "    ,          ");
 
 
}

結果は
image
 
明らかに、私が直接Parentからオブジェクトを取得すると、Containsはこのオブジェクトを捕まえます.
 
では、私が値の比較が必要だとしたら、どうすればいいのでしょうか.
 
簡単です.predicate委任を定義して、比較方法を指定できます.
/// <summary>
///RemoveDiscendantPower    
///</summary>
[TestMethod()]
public void RemoveDiscendantPowerTest() {
    Power Parent = new Power
    {
        Alias = "testRoot",
        CanDelete = false,
        Description = "     ",
        id = 100,
        PowerName = "     ",
        Childs = new List<Power>
        {
            new Power{
                Alias = "testBranch1",
                CanDelete = true,
                Description = "    1",
                id = 100100,
                PowerName = "    1",
                Childs = new List<Power>{
                    new Power{
                     Alias = "leaf1",
                     CanDelete = true,
                     Description = "    1",
                     id = 100100100,
                     PowerName = "    1"
                    },
                    new Power{
                     Alias = "leaf2",
                     CanDelete = true,
                     Description = "    2",
                     id = 100100101,
                     PowerName = "    2"
                    }
                }
            },
            new Power{
                Alias ="testBranch2",
                CanDelete = true,
                Description = "    2",
                id = 100101,
                PowerName = "    2",
                Childs = new List<Power>{
                    new Power{
                     Alias = "leaf3",
                     CanDelete = true,
                     Description = "    3",
                     id = 100101100,
                     PowerName = "    3"
                    },
                    new Power{
                     Alias = "leaf4",
                     CanDelete = true,
                     Description = "    4",
                     id = 100101101,
                     PowerName = "    4"
                    }
                }
                
            }
        }
    }; // TODO:         
    Power Discendant = new Power{
                     Alias = "leaf4",
                     CanDelete = true,
                     Description = "    4",
                     id = 100101101,
                     PowerName = "    4"
                    };
    // TODO:         
 
 
    //Assert.IsTrue(Parent.Childs[1].Childs.Contains(Discendant), "    ,Contains    ");
 
 
 
    //Power test = Parent.Childs[1].Childs[1];
 
    //Assert.IsTrue(Parent.Childs[1].Childs.Contains(test), "    ,          ");
    Assert.IsTrue(Parent.Childs[1].Childs.Exists(delegate(Power t) {
        return t.id == 100101101;
    }));
 
}

(ここではPredicate委任を明示的に宣言する代わりに匿名委任を使用します)
テストに簡単に合格
image
 
OK,依頼の比較実行に成功した.
 
結論
================================
ListのContainsはオブジェクトに対する「メモリ検出」であり、
リストに宣言したオブジェクトと同じ値のオブジェクトがあるかどうかを確認したい場合
Existsメソッドが必要であり、比較方法を指定するためにPredicate委任を実現する必要があります.
================================