I'm creating my own HashSet that works as the standard HashSet, using a Dictionary. I'm doing this because C# for XNA XBox doesn't support HashSets.
This code is based on code from an example I found. I've edited the example to fix some of the problems but it still won't compile.
public class HashSet2<T> : ICollection<T>
{
private Dictionary<T, Int16> dict;
// code has been edited out of this example
// see further on in the question for the full class
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return dict.GetEnumerator();
}
}
.
'HashSet2<T>' does not implement interface member
'System.Collections.IEnumerable.GetEnumerator()'.
'HashSet2<T>.GetEnumerator()' cannot implement
'System.Collections.IEnumerable.GetEnumerator()'
because it does not have the matching return type of
'System.Collections.IEnumerator'
I'd also be grateful for information on fixing it to be more like the standard HashSet if it deviates in it's behaviour or what it implments in ways that could be unexpected.
Continued from: stackoverflow.com/questions/9966336/c-sharp-xna-xbox-hashset-and-tuple
The most recent vertion of the class:
public class HashSet2<T> : ICollection<T>
{
private Dictionary<T, Int16> dict;
// Dictionary<T, bool>
public HashSet2()
{
dict = new Dictionary<T, short>();
}
public HashSet2(HashSet2<T> from)
{
dict = new Dictionary<T, short>();
foreach (T n in from)
dict.Add(n, 0);
}
public void Add(T item)
{
// The key of the dictionary is used but not the value.
dict.Add(item, 0);
}
public void Clear()
{
dict.Clear();
}
public bool Contains(T item)
{
return dict.ContainsKey(item);
}
public void CopyTo(
T[] array,
int arrayIndex)
{
throw new NotImplementedException();
}
public bool Remove(T item)
{
return dict.Remove(item);
}
public System.Collections.IEnumerator GetEnumerator()
{
return ((System.Collections.IEnumerable)
dict.Keys).GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return ((IEnumerable<T>)
dict.Keys).GetEnumerator();
}
public int Count
{
get {return dict.Keys.Count;}
}
public bool IsReadOnly
{
get {return false;}
}
}
You want to enumerate the keys, not the dictionary. Try this:
public IEnumerator GetEnumerator()
{
return ((IEnumerable)dict.Keys).GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return ((IEnumerable<T>)dict.Keys).GetEnumerator();
}
The point is that the HashSet's GetEnumerator
returns enumerator that enumerates keys of type T
while dictionary's GetEnumerator
returns enumerator that enumerates KeyValue object.
UPDATE
Change it to below:
public IEnumerator GetEnumerator()
{
dict.Keys.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return dict.Keys.GetEnumerator();
}
You can simply use Mono's HashSet<T>
. You might need to make some minor changes to #if
, or remove some interfaces/attributes, but it works on .net.
It's using the MIT X11 license, which is permissive. https://github.com/mono/mono/blob/master/mcs/class/System.Core/System.Collections.Generic/HashSet.cs
Just took a look at the source, and all implementations of GetEnumerator in the Dictionary<TKey, TValue>
return the KeyCollection.Enumerator
/ValueCollection.Enumerator
objects instead of IEnumerator<T>
(which is what we need). The good news is that the Key/ValueCollation.Enumerator
implement both System.Collection.IEnumerator
and IEnumerator<T>
interfaces, so you can safely cast to those types.
Try doing this instead:
public IEnumerator GetEnumerator()
{
return (IEnumerator)dict.Keys.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return (IEnumerator<T>)dict.Keys.GetEnumerator();
}
来源:https://stackoverflow.com/questions/10246572/c-sharp-hashset2-to-work-exactly-like-the-standard-c-sharp-hashset-not-compilin