Reputation: 155
I need help with overriding method IEnumerator<T>
. I want to have a dictionary class that during enumeration will return only elements, like dictionary.Values. It work in foreach, I suggest that because foreach use IEnumerator
instead of IEnumerator<T>
, but LINQ methods not work over instances of my class. If I try call linq method I get Could not find an implementation of the query pattern for source type. 'Where' not found.
public abstract class SpecialDictionary : Dictionary<TKey, MyClass>, IEnumerable<MyClass>
{
public Add(MaClass item)
{
Add(item.Id, item);
}
new public IEnumerator<MyClass> GetEnumerator()
{
return this.Values.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
I need collection of items with fast access to element by id. All elements have Guid id. This seemed like a good idea for me, but I welcome your suggestions of this solutions.
Upvotes: 3
Views: 195
Reputation: 1062492
The problem is that SpecialDictionary
now implements both IEnumerable<KeyValuePair<Guid,MyClass>>
and IEnumerable<MyClass>
. Because of this ambiguity, LINQ is unable to choose between these two options, and chooses neither. The extension methods still work, but require explicit type parameters:
MyClass item = dict.First<MyClass>();
and equally:
KeyValuePair<Guid, MyClass> pair = dict.First<KeyValuePair<Guid, MyClass>>();
LINQ, however, will not allow you to add explicit type parameters, so will not work. My advice: don't do that. If the user wants to work over the values, let them do so via .Values
.
Here's an example of encapsulation:
public class SpecialDictionary : IEnumerable<MyClass>
{
private readonly Dictionary<Guid, MyClass> inner = new Dictionary<Guid, MyClass>();
public void Add(MyClass item)
{
inner.Add(item.Id, item);
}
public MyClass this[Guid id]
{
get { return inner[id]; }
set { inner[id] = value; }
}
public bool TryGetValue(Guid id, out MyClass value)
{
return inner.TryGetValue(id, out value);
}
public IEnumerator<MyClass> GetEnumerator()
{
return inner.Values.GetEnumerator();
}
public int Count { get { return inner.Count; } }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Upvotes: 3