Why cannot I type foreach(var vari in variables)?
Well you can - but then vari
is implicitly of type object
.
You happen to know that each entry within the iterator is a DictionaryEntry
, but the compiler doesn't. As far as it's aware, the iteration element type of IDictionary
it just object
. Even though IDictionary.GetEnumerator
returns an IDictionaryEnumerator
, that still has a Current
property with a type of object
, not DictionaryEntry
.
Annoyingly, this could have been done better. If IDictionaryEnumerator
had been implemented using explicit interface implementation for IEnumerator.Current
, and provided a new Current
property of type DictionaryEntry
, then this would have worked and been more efficient as it would have avoided boxing.
Section 8.8.4 of the C# spec provides the rules the C# compiler uses to determine the element type of a collection.
EDIT: For those who wanted to see how IDictionaryEnumerator
could have been declared, here's a short but complete example. Note how this doesn't use generics anywhere, but does use var
in Main
, still with a variable implicitly typed as DictionaryEntry
:
using System;
using System.Collections;
interface IJonDictionary : IEnumerable
{
new IJonDictionaryEnumerator GetEnumerator();
}
interface IJonDictionaryEnumerator : IEnumerator
{
new DictionaryEntry Current { get; }
}
class JonDictionary : IJonDictionary
{
private readonly IDictionary dictionary = new Hashtable();
public object this[object key]
{
get { return dictionary[key]; }
set { dictionary[key] = value; }
}
public void Add(object key, object value)
{
dictionary.Add(key, value);
}
public IJonDictionaryEnumerator GetEnumerator()
{
return new JonEnumerator(dictionary.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
private class JonEnumerator : IJonDictionaryEnumerator
{
private readonly IDictionaryEnumerator enumerator;
internal JonEnumerator(IDictionaryEnumerator enumerator)
{
this.enumerator = enumerator;
}
public DictionaryEntry Current
{
get { return enumerator.Entry; }
}
object IEnumerator.Current { get { return Current; } }
public bool MoveNext()
{
return enumerator.MoveNext();
}
public void Reset()
{
enumerator.Reset();
}
}
}
class Program
{
static void Main(string[] args)
{
var dictionary = new JonDictionary {
{ "x", "foo" },
{ "y", "bar" }
};
foreach (var entry in dictionary)
{
Console.WriteLine("{0} = {1}", entry.Key, entry.Value);
}
}
}
IEnumerator
callsCurrent
fromIEnumerator
, so how could we provide a new implementation? I've just made an explicit implementation ofIEnumerator
with anotherCurrent
property returning my specified class, but it still does not work the way I intended. Could you please provide some sketch solution? – Incontrollable