我想将以下对象用作Dictionary键。如果类别和目标相等,则密钥相等。任何解决方案?
public class TargetKey
{
public TargetKey(Categories category_arg, String target_arg)
{
catetory = category_arg;
target = target_arg;
}
private Categories catetory;
public Categories Catetory
{
get { return catetory; }
//set { catetory = value; }
}
private String target;
public String Target
{
get { return target; }
//set { target = value; }
}
}
首先调用GetHashCode()
,如果散列等于,则调用Equals()
。
所以我添加了以下两种方法:
public override bool Equals(object obj)
{
TargetKey other = obj as TargetKey;
return other.Catetory == this.Catetory && other.Target == this.Target;
}
public override int GetHashCode()
{
return 0; //this will leads to ONLY 1 bucket, which defeat the idea of Dictionary.
}
public override bool Equals(object obj)
{
TargetKey other = obj as TargetKey;
return other.Catetory == this.Catetory && other.Target == this.Target;
}
public override int GetHashCode()
{
Int32 hash = this.Target.GetHashCode() + this.Catetory.GetHashCode();
// This will introduce some more buckets. Though may not be as many as possible.
return hash;
}
答案 0 :(得分:4)
根据您的类别和目标覆盖并实施Equals()
和GetHashCode()
,这样就可以将它们用作比较作为字典的关键字。
这是一个建议的实现,但究竟需要做什么将取决于它们是否为null。我假设它们可以在下面的实现中,因为构造函数中没有空检查:
public class TargetKey
{
public TargetKey(Categories category_arg, String target_arg)
{
Catetory = category_arg;
Target = target_arg;
}
private Categories catetory;
public Categories Catetory
{
get { return catetory; }
}
private String target;
public String Target
{
get { return target; }
}
public bool Equals (TargetKey other)
{
if (ReferenceEquals (null, other))
{
return false;
}
if (ReferenceEquals (this, other))
{
return true;
}
return Equals (other.catetory, catetory) && Equals (other.target, target);
}
public override bool Equals (object obj)
{
if (ReferenceEquals (null, obj))
{
return false;
}
if (ReferenceEquals (this, obj))
{
return true;
}
if (obj.GetType () != typeof (TargetKey))
{
return false;
}
return Equals ((TargetKey) obj);
}
public override int GetHashCode ()
{
unchecked
{
return ((catetory != null ? catetory.GetHashCode () : 0)*397) ^ (target != null ? target.GetHashCode () : 0);
}
}
}
答案 1 :(得分:1)
您可以覆盖GetHashCode和Equals。
Dictionary使用这两种方法来确定两个键是否相等。这也是它查找键值的方式。请参阅GetHashCode文档,了解Dictionary如何执行此操作。
[编辑]
查看哈希码的(非常)原始方法是作为大数组的索引。
bool ContainsKey(object key)
{
int hashCode = key.GetHashCode();
object foundKey = this.keys[hashCode];
return key.Equals(foundKey);
}
请注意,这是一种非常简化的字典实现方式。真正的字典不会有庞大的数组。真正的字典会进行空检查。真正的字典可以使用相同的哈希代码处理不同的密钥,尽管密钥类型会影响性能。等
答案 2 :(得分:0)
如果密钥是类的一部分,则使用KeyedCollection。 它是一个字典,其中键是从对象派生的。 在封面下它是字典。不必重复键和值中的键。 为什么键中的键与值不一样。不必在内存中复制相同的信息。
您没有定义类别或类别,因此使用了字符串。
KeyedCollection类
公开复合键的索引器
using System.Collections.ObjectModel;
namespace KeyCollStringString
{
class Program
{
static void Main(string[] args)
{
StringStringO ss1 = new StringStringO("Sall","John");
StringStringO ss2 = new StringStringO("Sall", "John");
if (ss1 == ss2) Console.WriteLine("same");
if (ss1.Equals(ss2)) Console.WriteLine("equals");
// that are equal but not the same I don't override = so I have both features
StringStringCollection stringStringCollection = new StringStringCollection();
// dont't have to repeat the key like Dictionary
stringStringCollection.Add(new StringStringO("Ringo", "Paul"));
stringStringCollection.Add(new StringStringO("Mary", "Paul"));
stringStringCollection.Add(ss1);
//this would thow a duplicate key error
//stringStringCollection.Add(ss2);
//this would thow a duplicate key error
//stringStringCollection.Add(new StringStringO("Ringo", "Paul"));
Console.WriteLine("count");
Console.WriteLine(stringStringCollection.Count.ToString());
// reference by ordinal postion (note the is not the long key)
Console.WriteLine("oridinal");
Console.WriteLine(stringStringCollection[0].GetHashCode().ToString());
// reference by index
Console.WriteLine("index");
Console.WriteLine(stringStringCollection["Mary", "Paul"].GetHashCode().ToString());
Console.WriteLine("foreach");
foreach (StringStringO ssO in stringStringCollection)
{
Console.WriteLine(string.Format("HashCode {0} String1 {1} String2 {2} ", ssO.GetHashCode(), ssO.String1, ssO.String2));
}
Console.WriteLine("sorted by date");
foreach (StringStringO ssO in stringStringCollection.OrderBy(x => x.String1).ThenBy(x => x.String2))
{
Console.WriteLine(string.Format("HashCode {0} String1 {1} String2 {2} ", ssO.GetHashCode(), ssO.String1, ssO.String2));
}
Console.ReadLine();
}
public class StringStringCollection : KeyedCollection<StringStringS, StringStringO>
{
// This parameterless constructor calls the base class constructor
// that specifies a dictionary threshold of 0, so that the internal
// dictionary is created as soon as an item is added to the
// collection.
//
public StringStringCollection() : base(null, 0) { }
// This is the only method that absolutely must be overridden,
// because without it the KeyedCollection cannot extract the
// keys from the items.
//
protected override StringStringS GetKeyForItem(StringStringO item)
{
// In this example, the key is the part number.
return item.StringStringS;
}
// indexer
public StringStringO this[string String1, string String2]
{
get { return this[new StringStringS(String1, String2)]; }
}
}
public struct StringStringS
{ // required as KeyCollection Key must be a single item
// but you don't reaaly need to interact with Int32Int32s
public readonly String String1, String2;
public StringStringS(string string1, string string2) { this.String1 = string1.Trim(); this.String2 = string2.Trim(); }
}
public class StringStringO : Object
{
// implement you properties
public StringStringS StringStringS { get; private set; }
public String String1 { get { return StringStringS.String1; } }
public String String2 { get { return StringStringS.String2; } }
public override bool Equals(Object obj)
{
//Check for null and compare run-time types.
if (obj == null || !(obj is StringStringO)) return false;
StringStringO item = (StringStringO)obj;
return (this.String1 == item.String1 && this.String2 == item.String2);
}
public override int GetHashCode()
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + String1.GetHashCode();
hash = hash * 23 + String1.GetHashCode();
return hash;
}
public StringStringO(string string1, string string2)
{
StringStringS stringStringS = new StringStringS(string1, string2);
this.StringStringS = stringStringS;
}
}
}
}
答案 3 :(得分:-1)
只需使用通用字典集(C#代码)
Dictionary<TargetKey> objMyCollection = new Dictionary<TargetKey>.();
使用objMyCollection的ContainsKey()方法,如:
if(objMyCollection.ContainsKey(new TargetKey())
{
MessageBox.Show("Obj find");
}
else
{
MessageBox.Show("key not found add new one");
}