2012-02-19 1 views
2

여기에 뭔가가 빠졌는지 모르겠지만 다음 코드는 항상 List.Contains 부분에 예외가 발생한다는 것을 이상하게 생각하지는 않습니다. 목록에 해당 요소가 포함되어 있음을 알고 있습니다. Contains 방법의 documentation에서List.Contains 이상한 동작

using System; 
using System.Linq; 
using System.Collections.Generic; 

class SomeClass 
{ 
    public string param1 {get; private set;} 
    public string param2 {get; private set;} 

    private SomeClass(){} 
    public SomeClass(string param1, string param2) 
    { 
    this.param1 = param1; 
    this.param2 = param2; 
    } 
} 

class SomeClass2 
{ 
    private List<SomeClass> myList = new List<SomeClass>(); 

    public void Add(SomeClass someclass) 
    { 
    myList.Add(someclass); 
    } 

    public void Remove(SomeClass someClass) 
    { 
    // this part always rises an exception 
    if(!myList.Contains(someClass)) 
     throw new System.ArgumentException("some error"); 
    else myList.Remove(someClass); 
    } 
} 

class MainClass 
{ 
    public static void Main (string[] args) 
    { 
    var _someClass = new SomeClass2();   
    _someClass.Add(new SomeClass("aaa", "bbb")); 

    try 
    { 
     _someClass.Remove(new SomeClass("aaa", "bbb")); 
    } 
    catch(Exception e) 
    { 
     Console.WriteLine(e.Message); 
    } 
    } 
} 
+0

여기 뭔가 문제가 있습니다. 아직이 컴퓨터에 컴파일러가 설치되어 있지 않지만 예제를 컴파일하는 방법을 모르므로 설치하려고합니다. –

+0

소음 때문에 미안하지만 컴파일러가없는 클래스 생성자와 클래스 정의의 차이점을 알 수는 없습니다 ... –

답변

3

견적 (T에) IEquatable의 목적을 구현 .Equals 의해 정의

이 방법은, 기본 같음 비교자를 통해 어떤지를 판정한다 T (목록에있는 값의 유형).

class SomeClassEqualityComparer : IEqualityComparer<SomeClass> 
{ 
    private static readonly SomeClassEqualityComparer _instance = new SomeClassEqualityComparer(); 

    public bool Equals(SomeClass x, SomeClass y) 
    { 
     return x.param1 == y.param1 && x.param2 == y.param2; 
    } 

    public int GetHashCode(SomeClass obj) 
    { 
     unchecked 
     { 
      int hash = 17; 
      hash = hash * 23 + obj.param1.GetHashCode(); 
      hash = hash * 23 + obj.param2.GetHashCode(); 
      return hash; 
     } 
    } 

    public static IEqualityComparer<SomeClass> Instance 
    { 
     get { return _instance; } 
    } 
} 
:

class SomeClass: IEquatable<SomeClass> 
{ 
    public string param1 { get; private set; } 
    public string param2 { get; private set; } 

    private SomeClass() { } 
    public SomeClass(string param1, string param2) 
    { 
     this.param1 = param1; 
     this.param2 = param2; 
    } 

    public bool Equals(SomeClass other) 
    { 
     return param1 == other.param1 && param2 == other.param2; 
    } 
} 

또 다른 가능성은 사용자 정의 EqualityComparer<T>을 구현하는 것입니다 : 당신이 SomeClass의 두 인스턴스가 같은지 경우가 결정하는 방법을 포함하려는 경우

그래서 당신은 당신의 객체에 IEquatable<T>을 구현할 수

다음 Contains 메서드를 사용하여 다음과 같은 오버로드를 사용하십시오.

if (!myList.Contains(someClass, SomeClassEqualityComparer.Instance)) 
    throw new System.ArgumentException("some error"); 
+0

세부 사항을 확인하지 못했습니다 :/Thanks – user1219206

+0

글쎄, (Eq)': D –

+0

IEqualityComparer를 사용하면 SomeClass가 그다지 유용하지 않게되는 것처럼 보일 것입니다. 그럼 다시, 당신은 someclasses 전체를 가지고 효율적으로 IEqualityComparer (바닐라 반사 아마도 그것을 자르지 않을 것입니다) 쓸 수있는 경우 당신은 어느 dev에 노력이나 pcode 가져 오기 시간을 절약 할 수있을 수도 있습니다. –

0

SomeClass의 동일한 인스턴스를 제거하지 않을 것입니다. 이것은 작동합니다 :

public static void Main() 
{ 
    var _someClass = new SomeClass2(); 

    var someClass = new SomeClass("aaa", "bbb"); 
    _someClass.Add(someClass); 

    try 
    { 
     _someClass.Remove(someClass); 
    } 
    catch(Exception e) 
    { 
     Console.WriteLine(e.Message); 
    } 
} 

당신은 IEquatable을 구현해야합니다. http://msdn.microsoft.com/en-us/library/bhkz42b3.aspx을 참조하십시오.

+0

해결 방법은 다음과 같습니다. –

0

죄송합니다. 해시 코드 구현에 더 많은 시간을 투자하지 않았습니다. 나는 ^가 올바른 xor 연산자인지 기억조차하지 않는다. 나는 xor 전에 rot13 할 수 있다고 생각한다. 그러나 그것은 어리석은 것처럼 보였다.

using System; 
using System.Collections.Generic; 

namespace DoesItCompile 
{ 
    class SomeClass 
    { 
     private object param1; 
     private object param2; 
     private SomeClass() { } 
     public SomeClass(string param1, string param2) 
     { 
      this.param1 = param1; 
      this.param2 = param2; 
     } 

     public override bool Equals(object oThat) 
     { 
      if (!(oThat is SomeClass)) 
       return false; 
      SomeClass scThat = (SomeClass)oThat; 
      if (!string.Equals(this.param1, scThat.param1)) 
       return false; 
      if (!string.Equals(this.param2, scThat.param2)) 
       return false; 
      return true; 
     } 

     public override int GetHashCode() 
     { 
      return this.param1.GetHashCode()^this.param2.GetHashCode(); 
     } 
    } 

    class SomeClass2 
    { 
     private List<SomeClass> myList = new List<SomeClass>(); 

     public void Add(SomeClass someclass) 
     { 
      myList.Add(someclass); 
     } 

     public void Remove(SomeClass someClass) 
     { 
      // this part always rises an exception 
      if (!myList.Contains(someClass)) 
       throw new System.ArgumentException("some error"); 

      else myList.Remove(someClass); 
     } 
    } 

    class MainClass 
    { 
     public static void Main(string[] args) 
     { 
      var _someClass = new SomeClass2(); 

      _someClass.Add(new SomeClass("aaa", "bbb")); 

      try 
      { 
       _someClass.Remove(new SomeClass("aaa", "bbb")); 

       Console.WriteLine("Have a nice president's day."); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e); 
      } 

      Console.ReadKey(); 
     } 
    } 
} 

P. - 젤다 스토커를 데려온 이유는 모르겠지만 좋은 이유가있을거야.