C# 使用HashSet作为字典键-比较所有元素

C# 使用HashSet作为字典键-比较所有元素,c#,dictionary,hashset,edges,C#,Dictionary,Hashset,Edges,我正在检查整个边组是否已包含两点之间的连接 我想使用包含两个向量的哈希集,作为字典键。然后我希望能够调用performantDictionary.ContainsKey(hashSet)。我希望包含/相等检查依赖于集合中的向量 氧化铁。如果我将HashSet[v000v001]添加到Dict中,我希望得到Dictionary.ContainsKey(HashSet[V001 V000])返回true。(HashSet,因此顺序可以不同,只是相同的元素) 问题似乎是,Dictionary.Cont

我正在检查整个边组是否已包含两点之间的连接

我想使用包含两个向量的
哈希集
,作为
字典
键。然后我希望能够调用performant
Dictionary.ContainsKey(hashSet)
。我希望包含/相等检查依赖于集合中的向量

氧化铁。如果我将
HashSet[v000v001]
添加到Dict中,我希望得到
Dictionary.ContainsKey(HashSet[V001 V000])
返回true。(HashSet,因此顺序可以不同,只是相同的元素)

问题似乎是,
Dictionary.ContainsKey()
方法确实将单独创建的
hashset
视为不同的对象,即使它们包含相同的元素

Dictionary<HashSet<Vector3>, Vector3> d = new Dictionary<HashSet<Vector3>, Vector3>();

HashSet<Vector3> s = new HashSet<Vector3>();
s.Add(Vector3.one);
s.Add(Vector3.zero);

d.Add(s);

HashSet<Vector3> s2 = new HashSet<Vector3>();
s2.Add(Vector3.zero);
s2.Add(Vector3.one);

bool doesContain = d.ContainsKey(s2); // should be true
Dictionary d=newdictionary();
HashSet s=新的HashSet();
s、 添加(矢量3.1);
s、 加法(矢量3.0);
d、 添加(s);
HashSet s2=新的HashSet();
s2.相加(矢量3.零);
s2.添加(矢量3.1);
bool doesContain=d.ContainsKey(s2);//应该是真的

您还可以建议一种更好的方法来有效地执行“Contains()”检查。

HashSet类型无法进行您想要的即时相等比较。它只有引用等式

要获得所需的内容,需要使用新类型作为字典键。新类型将具有HashSet属性,并重载
Equals()
GetHashCode()
,此时还可以实现
IEquatable

我会让你开始:

public class HashKey<T> : IEquatable<HashKey<T>>
{
    private HashSet<T> _items;
    public HashSet<T> Items
    {
        get {return _items;}
        private set {_items = value;}
    }

    public HashKey()
    {
        _items = new HashSet<T>();
    }
    public HashKey(HashSet<T> initialSet)
    {
        _items = initialSet ?? new HashSet();
    }

    public override int GetHashCode()
    {
        // I'm leaving this for you to do
    }

    public override bool Equals(Object obj)
    {
        if (! (obj is HashKey)) return false;
        return this.GetHashCode().Equals(obj.GetHashCode());
    }

    public bool Equals(HashSet<T> obj)
    {
        if (obj is null) return false;
        return this.GetHashCode().Equals(obj.GetHashCode());
    }
}      
公共类HashKey:IEquatable
{
私有HashSet_项;
公共哈希集项
{
获取{return\u items;}
私有集{u items=value;}
}
公钥
{
_items=newhashset();
}
公共HashKey(HashSet initialSet)
{
_items=initialSet??新HashSet();
}
公共覆盖int GetHashCode()
{
//我把这件事留给你做
}
公共覆盖布尔等于(对象对象对象)
{
如果(!(obj是HashKey))返回false;
返回此.GetHashCode().Equals(obj.GetHashCode());
}
公共布尔等于(HashSet obj)
{
如果(obj为空)返回false;
返回此.GetHashCode().Equals(obj.GetHashCode());
}
}      

您想使用哈希集作为键

所以键是引用,其中一个键是一个hashset引用

容器可以比较引用

对于要执行的操作,可以创建一个实现IEqualityComparer的类,将其传递给字典构造函数

如果你想要一个完整的管理,你应该创建一个嵌入字典的新类,并实现你自己的公共操作来包装字典:ContainsKey和所有你需要的其他方法

public class MyDictionary : IEnumerable<>
{

  private Dictionary<HashSet<Vector3>, Vector3> d 
    = new Dictionary<HashSet<Vector3>, Vector3>();

  public int Count { get; }

  public this...

  public ContainsKey()
  {
    // implements your own comparison algorithm
  }

  public Add();

  public Remove();

  ...

}
公共类MyDictionary:IEnumerable
{
私人词典d
=新字典();
公共整数计数{get;}
公开这个。。。
公共容器
{
//实现您自己的比较算法
}
公共添加();
公众移除();
...
}

因此,您将有一个强类型字典用于您的预期用途。

您需要一个新类型用作字典键。新类型将有一个Hashset属性,并重载
.Equals()
GetHashCode()
(因此也可以实现
IEquatable
)来进行所需的比较。
HashSet
类型不提供您想要的开箱即用的相等比较。它只是引用平等。不要因为我是新来的就否决我的问题。。。非常不礼貌@JoelCoehoorn这似乎是一个非常好的方法,但我不完全理解我需要在哪里覆盖这些东西。你能给出一个小的代码示例吗?Dictionary有一个接受自定义IEqualityComparer的构造函数:@Mechandrius这个问题被否决了,因为你没有表现出任何努力或研究来解决这个问题。如果你是新来的,我真的建议你阅读所有的帮助部分,同时也要阅读Jon Skeet的。确保你的问题尽可能好将有助于你获得更有利的结果。@DavidBrowne-Microsoft噢,我以前没有注意到这个问题。这可能是有用的。我要指出的一点是,一般来说,使用
GetHashCode
作为相等比较不是一个好主意(尽管我也很内疚于使用它),因为事实上,相等的对象必须返回相等的哈希码,这并不意味着具有相等哈希码的对象是相等的。Eric Lippert处理
GetHashCode
,并顺便提到了这一事实(鸽子洞原则)。@pstrjds普遍同意。。但在这种情况下,这实际上是这种类型存在的唯一原因。当然,以后总是会有范围/功能的蔓延。我可以看到并同意这一点:)就因为OP是一名学生,我想确保有人提到,一般来说,这不是“最佳实践”。这看起来就是答案。但是虽然我对这个问题不太了解,但感觉有点不对劲。谢谢你的回答。两种解决方案都很好。但是使用包装的HashSet键看起来非常简单和合适。当需要更多特殊属性时,重写整个字典可能会很有用。