C#中的多键字典?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1171812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multi-key dictionary in c#?
提问by SuperSuperDev1234
I know there isn't one in the BCL but can anyone point me to a good opensource one?
我知道 BCL 中没有一个,但有人能指点我一个好的开源吗?
By Multi I mean 2 keys. ;-)
多我的意思是2个键。;-)
回答by Adrian Godong
I'm currently simply concatenating the keys into a single string as a workaround. Of course, this will not work on non-string keys. Would love to know the answer as well.
我目前只是将键连接成一个字符串作为解决方法。当然,这不适用于非字符串键。也很想知道答案。
回答by jason
I use a Tuple
as the keys in a Dictionary
.
我使用 aTuple
作为a中的键Dictionary
。
public class Tuple<T1, T2> {
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
// implementation details
}
Be sure to override Equals
and GetHashCode
and define operator!=
and operator==
as appropriate. You can expand the Tuple
to hold more items as needed. .NET 4.0 will include a built-in Tuple
.
一定要覆盖Equals
和GetHashCode
定义operator!=
和operator==
适当。您可以Tuple
根据需要展开以容纳更多项目。.NET 4.0 将包含一个内置的Tuple
.
回答by Charles Bretana
Tuples will be (are) in .Net 4.0 Until then, you can also use a
元组将(是)在 .Net 4.0 中,在此之前,您还可以使用
Dictionary<key1, Dictionary<key2, TypeObject>>
or, creating a custom collection class to represent this...
或者,创建一个自定义集合类来表示这个......
public class TwoKeyDictionary<K1, K2, T>:
Dictionary<K1, Dictionary<K2, T>> { }
or, with three keys...
或者,用三个键...
public class ThreeKeyDictionary<K1, K2, K3, T> :
Dictionary<K1, Dictionary<K2, Dictionary<K3, T>>> { }
回答by Simon P Stevens
Take a look at Wintellect's PowerCollections(CodePlex download). I think their MultiDictionary does something like that.
看看 Wintellect 的PowerCollections(CodePlex 下载)。我认为他们的 MultiDictionary 做了类似的事情。
It's a dictionary of dictionaries, so you have 2 keys to access each object, the key for the main dictionary to get you the required sub dictionary, and then the second key for the sub dictionary to get you the required item. Is that what you mean?
它是一个字典字典,因此您有 2 个键来访问每个对象,主字典的键可以为您提供所需的子字典,然后是子字典的第二个键,可以为您提供所需的项目。你是这个意思吗?
回答by Paul Ruane
I think you would need a Tuple2 like class. Be sure that it's GetHashCode() and Equals() is based upon the two contained elements.
我认为你需要一个像 Tuple2 这样的类。确保它的 GetHashCode() 和 Equals() 基于两个包含的元素。
See Tuples in C#
参见C# 中的元组
回答by JSB????
Is there anything wrong with
有什么问题吗
new Dictionary<KeyValuePair<object, object>, object>?
回答by Eamon Nerbonne
I've also used tuples as jason in his answerdoes. However, I suggest you simply define a tuple as a struct:
我也在jason 的回答中使用了元组。但是,我建议您简单地将元组定义为结构:
public struct Tuple<T1, T2> {
public readonly T1 Item1;
public readonly T2 Item2;
public Tuple(T1 item1, T2 item2) { Item1 = item1; Item2 = item2;}
}
public static class Tuple { // for type-inference goodness.
public static Tuple<T1,T2> Create<T1,T2>(T1 item1, T2 item2) {
return new Tuple<T1,T2>(item1, item2);
}
}
You get immutability, .GetHashcode
and .Equals
for free, which (while you're waiting for C# 4.0) is nice 'n simple...
你得到不变性,.GetHashcode
并.Equals
为自由故,两者(当你在等待C#4.0)是很好的“东经简单...
One warninghowever: the default GetHashcode
implementation (sometimes) only considers the first fieldso make sure to make the first field the most discriminating or implement GetHashcode
yourself (e.g. using FieldwiseHasher.Hash(this)
from ValueUtils), otherwise you'll likely run into scalability issues.
然而,一个警告:默认GetHashcode
实现(有时)仅考虑第一个字段,因此请确保使第一个字段成为最具辨别力的字段或GetHashcode
自己实现(例如使用FieldwiseHasher.Hash(this)
from ValueUtils),否则您可能会遇到可扩展性问题。
Also, you get to avoid nulls which tend to complicate matters (and if you really want nulls, you just make your Tuple<>
nullable). Slightly offtopic, am I the only one annoyed at the framework-level lack of support for non-null references? I work on large project, and occasionally a null creeps in somewhere it really shouldn't -- and hey presto, you get a nullreference exception -- but with a stack trace that points you to the reference's first usage, not the actually faulty code.
此外,您可以避免空值,这往往会使问题复杂化(如果您真的想要空值,只需将您的Tuple<>
空值设置为可空值)。有点题外话,我是唯一一个对框架级缺乏对非空引用的支持感到恼火的人吗?我在大型项目上工作,偶尔在不应该出现的地方出现空值——嘿,快,你会得到一个空引用异常——但是堆栈跟踪指向引用的第一次使用,而不是实际错误的代码.
Of course, .NET 4.0 is pretty old by now; most of us can just use .NET 4.0's tuple.
当然,.NET 4.0 现在已经很老了。我们大多数人只能使用 .NET 4.0 的元组。
Edit:to workaround the poor GetHashCode
implementation that .NET provides for structs I've written ValueUtils, which also allows you to use real names for your multi-field keys; that means you might write something like:
编辑:为了解决GetHashCode
.NET 为我编写的ValueUtils结构提供的糟糕实现,它还允许您为多字段键使用真实姓名;这意味着你可能会写一些类似的东西:
sealed class MyValueObject : ValueObject<MyValueObject> {
public DayOfWeek day;
public string NamedPart;
//properties work fine too
}
...which hopefully makes it easier to have human-readable names for data with value semantics, at least until some future version of C# implements proper tuples with named members; hopefully with decent hashcodes ;-).
...希望可以更容易地为具有值语义的数据提供人类可读的名称,至少在 C# 的某个未来版本实现具有命名成员的正确元组之前;希望有不错的哈希码;-)。
回答by Marcin Deptu?a
I've googled for this one: http://www.codeproject.com/KB/recipes/multikey-dictionary.aspx. I guess it's main feature compared to using struct to contain 2 keys in regular dictionary is that you can later reference by one of the keys, instead of having to supply 2 keys.
我用谷歌搜索过这个:http: //www.codeproject.com/KB/recipes/multikey-dictionary.aspx。我想与使用 struct 在常规字典中包含 2 个键相比,它的主要功能是您以后可以通过其中一个键进行引用,而不必提供 2 个键。
回答by maxwellb
Could you use a Dictionary<TKey1,Dictionary<TKey2,TValue>>
?
你能用Dictionary<TKey1,Dictionary<TKey2,TValue>>
吗?
You could even subclass this:
您甚至可以将其子类化:
public class DualKeyDictionary<TKey1,TKey2,TValue> : Dictionary<TKey1,Dictionary<TKey2,TValue>>
EDIT:This is now a duplicate answer. It also is limited in its practicality. While it does "work" and provide ability to code dict[key1][key2]
, there are lots of "workarounds" to get it to "just work".
编辑:这现在是一个重复的答案。它的实用性也受到限制。虽然它确实“工作”并提供了编码能力dict[key1][key2]
,但有很多“解决方法”可以让它“正常工作”。
HOWEVER:Just for kicks, one could implement Dictionary nonetheless, but at this point it gets a little verbose:
然而:只是为了踢球,人们仍然可以实现字典,但在这一点上它变得有点冗长:
public class DualKeyDictionary<TKey1, TKey2, TValue> : Dictionary<TKey1, Dictionary<TKey2, TValue>> , IDictionary< object[], TValue >
{
#region IDictionary<object[],TValue> Members
void IDictionary<object[], TValue>.Add( object[] key, TValue value )
{
if ( key == null || key.Length != 2 )
throw new ArgumentException( "Invalid Key" );
TKey1 key1 = key[0] as TKey1;
TKey2 key2 = key[1] as TKey2;
if ( !ContainsKey( key1 ) )
Add( key1, new Dictionary<TKey2, TValue>() );
this[key1][key2] = value;
}
bool IDictionary<object[], TValue>.ContainsKey( object[] key )
{
if ( key == null || key.Length != 2 )
throw new ArgumentException( "Invalid Key" );
TKey1 key1 = key[0] as TKey1;
TKey2 key2 = key[1] as TKey2;
if ( !ContainsKey( key1 ) )
return false;
if ( !this[key1].ContainsKey( key2 ) )
return false;
return true;
}
回答by Michael Donohue
Here's a fleshed out example of a pair class which can be used as the key to a Dictionary
.
这是一个可以用作Dictionary
.
public class Pair<T1, T2>
{
public T1 Left { get; private set; }
public T2 Right { get; private set; }
public Pair(T1 t1, T2 t2)
{
Left = t1;
Right = t2;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != typeof(Pair<T1, T2>)) return false;
return Equals((Pair<T1, T2>)obj);
}
public bool Equals(Pair<T1, T2> obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return Equals(obj.Left, Left) && Equals(obj.Right, Right);
}
public override int GetHashCode()
{
unchecked
{
return (Left.GetHashCode() * 397) ^ Right.GetHashCode();
}
}
}