2014-09-23 2 views
0

나는 dictionary<string,string>을 사용합니다. 키는 URL이고, 값은 이름입니다.사전에 동일한 키 값 유형의 반전을 피하십시오.

유형이 동일하므로 키 반전시 코드 오류를 피할 수있는 방법을 찾고 있습니다. 나는 Dictionary<UrlString,NameString>과 같은 것을 원했지만 봉인 되었기 때문에 문자열로부터 상속받은 내 자신의 유형을 만들 수 없습니다.

간단한 방법이 있습니까? 감사

+1

는 [ 'Url'] 시도 (http://msdn.microsoft.com/en-us/library/system.security.policy : 여기

두 변종 테스트와 코드 샘플이다 .url (v = vs.110) .aspx) 형식입니다. 또는 [Uri'] (http://msdn.microsoft.com/en-us/library/system.uri (v = vs.110) .aspx) 유형도 있습니다. 물론 –

+0

! 나는 어리 석음을 느낍니다. 감사합니다. – Julian50

+0

@AndreiV는 URL이 존재하기 때문에이 경우 ok입니다! 예를 들어 키가있는 사전 은 ID이고 값은 크기입니까? – Julian50

답변

2

첫째, 당신이 사용할 수있는 그러나

http://msdn.microsoft.com/en-us/library/system.uri(v=vs.110).aspx

, 당신은 디자인 할 수 Uri 클래스 자신의 클래스, 당신은 가 순서 EqualsGetHashCode을 구현하는 것입니다해야 할 유일한 것은 이 클래스를 사전 키 :

// You can implement in the same manner whatever domain you want: 
// Url, Size, Id, Voltage etc. 
public sealed class UrlString { 
    public UrlString(String address) { 
    if (Object.ReferenceEquals(null, address)) 
     throw new ArgumentNullException("address"); 

    Address = address; 
    } 

    public String Address { 
    get; 
    private set; 
    } 

    public override Boolean Equals(Object obj) { 
    if (Object.ReferenceEquals(obj, this)) 
     return true; 

    UrlString other = obj as UrlString; 

    if (Object.ReferenceEquals(other, null)) 
     return false; 

    return String.Equals(Address, other.Address, StringComparison.OrdinalIgnoreCase); 
    } 

    public override int GetHashCode() { 
    return String.IsNullOrEmpty(Address) ? 0 : Address.ToUpperInvariant().GetHashCode(); 
    } 
} 
+0

완벽한 감사합니다! – Julian50

0

일반적으로 비즈니스 함수에 대한 컬렉션을 사용자 정의하는 것은 좋지 않습니다. 일부 사용자 정의 메소드를 구현하는 것이 좋지만 확실히 할 수 있습니다.

이렇게하는 방법은 최소한 두 가지를 찾아 낼 수 있습니다. 1. 체크 인 생성자를 수행하는 암시 적 캐스트 연산자와 함께 사용자 지정 구조체를 사용합니다. 값 유형에 대해 작동합니다. 2. 초기 IDictionary 서명을 변경하지 않고 작동하므로 IEqualityComparer를 사용하면 더 좋습니다.

using System; 
using System.Collections.Generic; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace LimitingUseOfValueTypeAsDictionaryKey 
{ 
    public struct MySpecialInt 
    { 
     public int Target; 

     public MySpecialInt(int source) 
     { 
      if (source == 123) 
      { 
       throw new ArgumentOutOfRangeException("source"); 
      } 
      Target = source; 
     } 

     public static implicit operator int(MySpecialInt source) 
     { 
      return source.Target; 
     } 

     public static implicit operator MySpecialInt(int source) 
     { 
      return new MySpecialInt(source); 
     } 
    } 

    public class LimitingIntComparer : IEqualityComparer<int> 
    { 
     public int Compare(int x, int y) 
     { 
      return x.CompareTo(y); 
     } 

     public bool Equals(int x, int y) 
     { 
      return x.Equals(y); 
     } 

     public int GetHashCode(int source) 
     { 
      if (source == 123) 
      { 
       throw new ArgumentOutOfRangeException("source"); 
      } 
      return source.GetHashCode(); 
     } 
    } 

    public class LimitingStringComparer : IEqualityComparer<string> 
    { 
     public bool Equals(string x, string y) 
     { 
      return object.Equals(x, y); 
     } 

     public int GetHashCode(string source) 
     { 
      if (source == "123") 
      { 
       throw new ArgumentOutOfRangeException("source"); 
      } 
      return source.GetHashCode(); 
     } 
    } 

    [TestClass] 
    public class UnitTest1 
    { 
     [TestMethod] 
     public void CanTreatMySpecialIntAsRegularInt() 
     { 
      var a = 1; 
      MySpecialInt b = a; 
      Assert.AreEqual((int)b, 1); 
     } 

     [TestMethod] 
     public void CanUseOnlyAllowedValuesAsAKeyUsingCustomStruct() 
     { 
      var d = new Dictionary<MySpecialInt, string>(); 
      d.Add(1, "foo"); 

      try 
      { 
       d.Add(123, "bar"); 
      } 
      catch (ArgumentOutOfRangeException) 
      { 
       Console.WriteLine("Can't do that"); 
      } 

      Assert.AreEqual(1, d.Count); 
      Assert.AreEqual("foo", d[1]); 
     } 

     [TestMethod] 
     public void CanUseOnlyAllowedValuesAsAKeyUsingUsingComparer() 
     { 
      var d = new Dictionary<int, string>(new LimitingIntComparer()); 
      d.Add(1, "foo"); 

      try 
      { 
       d.Add(123, "bar"); 
      } 
      catch (ArgumentOutOfRangeException) 
      { 
       Console.WriteLine("Can't do that"); 
      } 

      Assert.AreEqual(1, d.Count); 
      Assert.AreEqual("foo", d[1]); 
     } 

     [TestMethod] 
     public void CanUseOnlyAllowedValuesAsAKeyUsingUsingComparerForStrings() 
     { 
      var d = new Dictionary<string, string>(new LimitingStringComparer()); 
      d.Add("1", "foo"); 

      try 
      { 
       d.Add("123", "bar"); 
      } 
      catch (ArgumentOutOfRangeException) 
      { 
       Console.WriteLine("Can't do that"); 
      } 

      Assert.AreEqual(1, d.Count); 
      Assert.AreEqual("foo", d["1"]); 
     } 
    } 
} 
관련 문제