您好我不明白为什么这段代码不起作用 - 它不会删除密钥;我的输出仍然是“2”。
Bencode.BencodeDict d = new myTorrent.Bencode.BencodeDict();
d.Dict.Add(new Bencode.BencodeString("info"), new Bencode.BencodeString("1"));
d.Dict.Add(new Bencode.BencodeString("info2"), new Bencode.BencodeString("2"));
d.Dict.Add(new Bencode.BencodeString("info3"), new Bencode.BencodeString("3"));
d.Remove(new Bencode.BencodeString("info2"));
Bencode.BencodeVariable s1;
s1 = d[new Bencode.BencodeString("info2")];
if (s1 != null)
Console.WriteLine(System.Text.UTF8Encoding.UTF8.GetString(s1.Encode()));
我的BencodeDict和BencodeString
namespace myTorrent.Bencode
{
class BencodeDict : BencodeVariable, IDictionary<BencodeString, BencodeVariable>
{
private Dictionary<BencodeString, BencodeVariable> dict;
public BencodeDict() {
this.dict = new Dictionary<BencodeString,BencodeVariable>();
}
protected override void InternalDecode(BinaryReader data) { /*...*/ }
public override long ByteLength() { /*...*/ }
public override byte[] Encode() { /*...*/ }
//#region Overridden Methods
public override bool Equals(object ob)
{
if (ob == null)
return false;
BencodeDict y = ob as BencodeDict;
if (this.dict.Count != y.dict.Count)
return false;
BencodeVariable val;
foreach (KeyValuePair<BencodeString, BencodeVariable> keypair in this.dict)
{
if (!y.TryGetValue(keypair.Key, out val))
return false;
if (!keypair.Value.Equals(val))
return false;
}
return true;
}
public override int GetHashCode()
{
int result = 0;
foreach (KeyValuePair<BencodeString, BencodeVariable> keypair in this.dict)
{
result ^= keypair.Key.GetHashCode();
result ^= keypair.Value.GetHashCode();
}
return result;
}
#region IDictionary and IList methods
public void Add(BencodeString key, BencodeVariable value)
{
this.dict.Add(key, value);
}
public void Add(KeyValuePair<BencodeString, BencodeVariable> item)
{
this.dict.Add(item.Key, item.Value);
}
public void Clear()
{
this.dict.Clear();
}
public bool Contains(KeyValuePair<BencodeString, BencodeVariable> item)
{
if (!this.dict.ContainsKey(item.Key))
return false;
return this.dict[item.Key].Equals(item.Value);
}
public bool ContainsKey(BencodeString key)
{
foreach(KeyValuePair<BencodeString, BencodeVariable> pair in this.dict) {
if (pair.Key.Equals(key))
return true;
}
return false;
}
public void CopyTo(KeyValuePair<BencodeString, BencodeVariable>[] array, int arrayIndex) { /*...*/ }
public int Count
{
get { return this.dict.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(BencodeString key)
{
return this.dict.Remove(key);
}
public bool Remove(KeyValuePair<BencodeString, BencodeVariable> item)
{
return this.dict.Remove(item.Key);
}
public bool TryGetValue(BencodeString key, out BencodeVariable value)
{
foreach(KeyValuePair<BencodeString, BencodeVariable> pair in this.dict)
if ( pair.Key.Equals(key) ) {
value = pair.Value;
return true;
}
value = null;
return false;
}
public BencodeVariable this[BencodeString key]
{
get {
foreach(KeyValuePair<BencodeString, BencodeVariable> pair in this.dict)
if ( pair.Key.Equals(key) )
return pair.Value;
return null;
}
set { this.dict[key] = value; }
}
public ICollection<BencodeString> Keys
{
get { return this.dict.Keys; }
}
public ICollection<BencodeVariable> Values
{
get { return this.dict.Values; }
}
public IEnumerator<KeyValuePair<BencodeString, BencodeVariable>> GetEnumerator()
{
return this.dict.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.dict.GetEnumerator();
}
#endregion
}
}
class BencodeString : BencodeVariable
{
private byte[] str;
public BencodeString() {
this.str = null;
}
public BencodeString(string str) {
this.str = encoding.GetBytes(str);
}
public override bool Equals(object ob)
{
if (ob == null)
return false;
BencodeString y = ob as BencodeString;
return (encoding.GetString(this.str) == encoding.GetString(y.str));
}
public override int GetHashCode()
{
return this.str.GetHashCode();
}
}
答案 0 :(得分:2)
你依靠byte[].GetHashCode()
做一些可取的事情。它不会。数组不实现相等或散列操作 - 您将获得默认(标识)行为。
重写您的GetHashCode
方法,如下所示:
public override int GetHashCode()
{
int result = 17;
foreach (byte b in str)
{
result = result * 31 + b;
}
return result;
}
(也不清楚encoding
是什么,但这是另一回事。)
请注意,如果Equals
是非空引用,则NullReferenceException
覆盖也会引发ob
,但不会BencodeString
。
编辑:假设您实际上想要检查字节数组是否相同,我不会在您的等式检查中调用Encoding.GetString
。毫无意义。只需直接检查字节数组内容即可。像这样的东西是一个合理的字节数组相等性检查 - 虽然我通常更喜欢写一个通用的等价物:
private static bool ArraysEqual(byte[] x, byte[] y)
{
if (x == y)
{
return true;
}
if (x == null || y == null)
{
return false;
}
if (x.Length != y.Length)
{
return false;
}
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i])
{
return false;
}
}
return true;
}
如果你做想要检查两个字节数组是否被解码为相等的字符串,那么你应该在两个地方使用Encoding.GetString
......但这很少是适当的做,IMO。
请注意,不清楚为什么你有自己的类字符串类开始。这里存在各种潜在问题......不均等编码,空引用等。
答案 1 :(得分:1)
Equal的值也产生相同的哈希码非常重要。这是一个明显(但不一定有效)的解决方法:
public override int GetHashCode()
{
return encoding.GetString(this.str).GetHashCode();
}
使字符串在内部不像Unicode字符串那样是一种代码味道,但在这里可能是故意的。它通常应用于外部接口。您的实现将允许在读取字符串后更改编码。但是一个非常严重的问题是字典在发生时不再有效。你将无法找到钥匙。