我使用dictionary<string,string>
。 键是一个url,Value是一个名字。字典避免使用相同的键值类型
由于类型相同,我寻找一种方法来避免编码错误时的键值倒置。 我想要这样的Dictionary<UrlString,NameString>
,但我不能创建我自己的字符串类型继承,因为是密封的。
那么有没有简单的方法? 感谢
我使用dictionary<string,string>
。 键是一个url,Value是一个名字。字典避免使用相同的键值类型
由于类型相同,我寻找一种方法来避免编码错误时的键值倒置。 我想要这样的Dictionary<UrlString,NameString>
,但我不能创建我自己的字符串类型继承,因为是密封的。
那么有没有简单的方法? 感谢
首先,你可以使用Uri
类
http://msdn.microsoft.com/en-us/library/system.uri(v=vs.110).aspx
但是,你可以设计自己的类,你所要做的 是落实以Equals
和GetHashCode
的唯一的事情使用该类作为 字典密钥:
// 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();
}
}
非常感谢! – Julian50 2014-09-23 08:16:18
一般来说,为业务功能定制集合不是一个好习惯,最好是实现一些自定义方法,但是您当然可以。
我可以弄清楚至少有两种方法。 1.使用具有隐式转换运算符的自定义结构,该运算符执行构造函数中的检查。适用于值类型。 2.使用IEqualityComparer更好,因为它不改变初始IDictionary签名。
下面是代码样品与试验两种变体:
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"]);
}
}
}
尝试['Url'](http://msdn.microsoft.com/en-us/library/system.security.policy .url(v = vs.110).aspx)类型。甚至是['Uri'](http://msdn.microsoft.com/zh-cn/library/system.uri(v = vs.110).aspx)类型。当然是 – 2014-09-23 08:02:11
!!我感觉很蠢..谢谢 – Julian50 2014-09-23 08:05:19
@AndreiV这种情况确定,因为URL存在!但例如字典与关键是一个id和值是一个大小? –
Julian50
2014-09-23 08:07:56