I have a wrapper struct for a Dictionary and I want to add a collection initializer to this class that adds my entries to the wrapped Dictionary.
public readonly struct Wrapper : IEnumerable<KeyValuePair<string, string>>
{
public Dictionary<string, string> Instance { get; }
public Wrapper()
{
Instance = new Dictionary<string, string>();
}
public void Add(string key, string value)
{
Instance.Add(key, value);
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return Instance.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
However, GetEnumerator call will cause boxing as Dictionary‘s enumerator is a struct. Is there any way around this?
>Solution :
The built-in Dictionary‘s implementations of IEnumerable.GetEnumerator and IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator box the return value too. It can’t not do that, since IEnumerable requires you to return an interface type.
It’s just that Dictionary also defines its own GetEnumerator, that is not required by IEnumerable or IEnumerable<T>. This GetEnumerator returns the struct directly, without boxing.
So when you call GetEnumerator through the IEnumerator interface, the return value will still be boxed. It’s only when you call GetEnumerator directly on a dictionary, that it will not be boxed.
If that’s what you are after, you can do what Dictionary does and declare three methods too:
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator()
=> GetEnumerator();
public Dictionary<string, string>.Enumerator GetEnumerator()
=> Instance.GetEnumerator();
See also the source code of Dictionary in .NET, especially lines 1132, 365, and 367, where the 3 methods are declared.