Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用列表<;customObject>;作为字典键c#_C#_C# 4.0 - Fatal编程技术网

使用列表<;customObject>;作为字典键c#

使用列表<;customObject>;作为字典键c#,c#,c#-4.0,C#,C# 4.0,我有一本字典,它的关键是一个列表,如下所示 var dict = new Dictionary<List<MyKey>, Emp>(new MyCustomComparer()); 比较器类 public class MyCustomComparer : IEqualityComparer<List<MyKey>> { public bool Equals(List<MyKey> x, List<MyKey> y)

我有一本字典,它的关键是一个列表,如下所示

var dict = new Dictionary<List<MyKey>, Emp>(new MyCustomComparer());
比较器类

public class MyCustomComparer : IEqualityComparer<List<MyKey>>
{
    public bool Equals(List<MyKey> x, List<MyKey> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<MyKey> obj)
    {
        return string.Join(",", obj.Select(s => s.Name)).GetHashCode();
    }

}
public class MyCustomComparer : IEqualityComparer<IEnumerable<MyKey>>
{
    public bool Equals(IEnumerable<MyKey> x, IEnumerable<MyKey> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IEnumerable<MyKey> obj)
    {
        return string.Join(",", obj.Select(s => s.Name)).GetHashCode();
    }

}
公共类MyCustomComparer:IEqualityComparer
{
公共布尔等于(列表x、列表y)
{
返回x.x(y);
}
public int GetHashCode(列表对象)
{
返回string.Join(“,”,obj.Select(s=>s.Name)).GetHashCode();
}
}
任何帮助都将不胜感激


关于发布更改的代码

    var dict = new Dictionary<List<MyKey>, Emp>(new MyCustomComparer());

    var key1 = new List<MyKey>
                   {
                       {new MyKey{ Name = "string1"}}
                   };

    dict.Add(key1, new Emp());
    var key2 = new List<MyKey>
                   {
                       {new MyKey{ Name = "string1"}}
                   };


    if (!dict.ContainsKey(key2))
    {
        dict.Add(key2, new Emp());
    }


public class MyKey
{
    public string Name { get; set; }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        var myKey = obj as MyKey;
        if (myKey != null)
        {
            return Name == myKey.Name;
        }
        return false;
    }
}

public class Emp
{
}
var dict=newdictionary(new MyCustomComparer());
var key1=新列表
{
{new MyKey{Name=“string1”}
};
dict.Add(键1,新Emp());
var key2=新列表
{
{new MyKey{Name=“string1”}
};
如果(!dict.ContainsKey(键2))
{
dict.Add(键2,新Emp());
}
公共类MyKey
{
公共字符串名称{get;set;}
公共覆盖int GetHashCode()
{
返回Name.GetHashCode();
}
公共覆盖布尔等于(对象对象对象)
{
var myKey=obj作为myKey;
如果(myKey!=null)
{
返回Name==myKey.Name;
}
返回false;
}
}
公共级电磁脉冲
{
}
比较器类

public class MyCustomComparer : IEqualityComparer<List<MyKey>>
{
    public bool Equals(List<MyKey> x, List<MyKey> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(List<MyKey> obj)
    {
        return string.Join(",", obj.Select(s => s.Name)).GetHashCode();
    }

}
public class MyCustomComparer : IEqualityComparer<IEnumerable<MyKey>>
{
    public bool Equals(IEnumerable<MyKey> x, IEnumerable<MyKey> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IEnumerable<MyKey> obj)
    {
        return string.Join(",", obj.Select(s => s.Name)).GetHashCode();
    }

}
公共类MyCustomComparer:IEqualityComparer
{
公共布尔等于(IEnumerable x,IEnumerable y)
{
返回x.x(y);
}
public int GetHashCode(IEnumerable obj)
{
返回string.Join(“,”,obj.Select(s=>s.Name)).GetHashCode();
}
}
另一种方法:

    public class MyCustomKey : ReadOnlyCollection<MyKey>
    {
        public override int GetHashCode()
        {
            return this.Aggregate(0, (c, i) => c + i.Name.GetHashCode()*i.Name.Length);
        }

        public override bool Equals(object obj)
        {
            var myKey = obj as MyCustomKey;
            if (myKey!= null && myKey.Count == this.Count)
            {
                return myKey.Zip(this, (i, j) => i.Name == j.Name).All(i=>i);
            }
            return false;
        }
    }

    var dict = new Dictionary<MyCustomKey, Emp>();

    var key1 = new MyCustomKey(new[] {new MyKey {Name = "string1"}});
    dict.Add(key1, new Emp());
    var key2 = new MyCustomKey(new[] {new MyKey {Name = "string1"}});

    if (!dict.ContainsKey(key2))
    {
         dict.Add(key2, new Emp());
    }
公共类MyCustomKey:ReadOnlyCollection
{
公共覆盖int GetHashCode()
{
返回此.Aggregate(0,(c,i)=>c+i.Name.GetHashCode()*i.Name.Length);
}
公共覆盖布尔等于(对象对象对象)
{
var myKey=obj作为MyCustomKey;
if(myKey!=null&&myKey.Count==this.Count)
{
返回myKey.Zip(this,(i,j)=>i.Name==j.Name).All(i=>i);
}
返回false;
}
}
var dict=新字典();
var key1=new MyCustomKey(new[]{new MyKey{Name=“string1”});
dict.Add(键1,新Emp());
var key2=new MyCustomKey(new[]{new MyKey{Name=“string1”});
如果(!dict.ContainsKey(键2))
{
dict.Add(键2,新Emp());
}

MyKey
类中没有
GetHashCode
Equals
实现,因此
SequenceEqual
中的比较将比较引用,而不是
Name
属性的值。您的
GetHashCode()
也是一个问题,它获取返回的
IEnumerable
的哈希代码。但你更大的问题是,如果你改变其中一个列表,而它正在执行滚动作为一个关键,它会打破字典。字典不能处理在执行键滚动时发生变化的对象。@PrestonGuillot:这将是关于在键类型中使用
Equals
GetHashCode
,但是的,这就是它的本质。除了@ScottChamberlain之外,你至少应该使用
ReadOnlyCollection
而不是
List
。将可变结构作为字典键可能会让你头疼。。。其次,
MyCustomComparer
GetHashCode
正在返回
IEnumerable
的哈希代码,而不是从Name属性返回。我想你忘了连接字符串了?而且,即使你使用一个不可变的列表,并在
MyKey
上实现
GetHashCode
Equals
来依赖
MyKey.Name
,你仍然会遇到一个问题,
MyKey.Name
是可变的-如果用作键的列表中该属性的值发生变化,然后字典就会坏了。一般提示:不要将可变对象用作字典的键。虽然这确实解决了您的直接问题,但如果在将列表添加到字典后对其进行修改,则会遇到问题。要查看此操作,请将
key1
设置为空列表,然后调用
dict.Add(key1,new Emp())
然后执行
key1.Add(new MyKey{Name=“string1”})
然后不经修改地运行程序的其余部分。如果任何名称中有逗号,则比较器很容易被破坏。您不应该将字符串压缩在一起,而应该将每个字符串的哈希值组合在一起。@Servy我同意他不应该将字符串组合在一起,但名称中的逗号不会打断它。事实上,他也可以轻松地执行
string.Join(“,obj.Select(s=>s.Name))
字符串从不被“查看”,它只被用作生成哈希代码的不透明块。@ScottChamberlain在这种情况下,他的
等于
检查已正确完成,因此是的,这只会增加他的冲突率,而不是导致不正确的行为。我习惯于看到人们在这两个地方使用相同的模式,导致可能的误报。@ScottChamberlain您的建议是什么?@PrestonGuillot事实上,这个问题的公认答案是,现在是从列表继承的最佳时机。海报所做的只是扩展列表的行为,以支持生成哈希代码,并等于使用列表中的成员。列表仍然只表示一个列表,它只是修改了相等行为。@ScottChamberlain我认为键必须/应该是不可变的,因为列表不是,所以类实际上并不表示列表。我想买ReadOnlyCollection。谢谢,我已经编辑了我的答案,使之成为不可变键