考虑以下代码:

var variables = System.Environment.GetEnvironmentVariables();
foreach (DictionaryEntry vari in variables)
{
    Console.WriteLine(vari.Key);
    Console.WriteLine(vari.Value);
}

它工作正常。由于variablesIDictionary,因此它由DictionaryEntry以及object Keyobject Value组成。

为什么我不能输入foreach(var vari in variables)?它给我
error CS1061: 'object' does not contain a definition for 'Key/Value'...

似乎很奇怪,我找不到这种行为的原因。 DictionaryEntrystruct,但是我可以遍历List<DictionaryEntry>很好。我当然知道IDictionary不是通用的,但是manual说它包含DictionaryEntries,因此应该可以使用var ...

最佳答案



可以,但是vari隐式为object类型。

您碰巧知道迭代器中的每个条目都是一个DictionaryEntry,但编译器并非如此。据了解,IDictionary的迭代元素类型只是object。即使IDictionary.GetEnumerator返回 IDictionaryEnumerator ,它仍然具有Current属性,其类型为object,而不是DictionaryEntry

令人讨厌的是,这本来可以做得更好。如果IDictionaryEnumerator已使用IEnumerator.Current的显式接口(interface)实现来实现,并提供了Current类型的新DictionaryEntry属性,则该方法将有效并且效率更高,因为它可以避免装箱。

C#规范的8.8.4节提供了C#编译器用来确定集合的元素类型的规则。

编辑:对于那些想看看如何可以声明IDictionaryEnumerator的人,这是一个简短但完整的示例。请注意,这怎么不会在任何地方使用泛型,但是会在var中使用Main,但仍带有一个隐式键入为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);
        }
    }
}

关于c# - 使用隐式DictionaryEntry遍历IDictionary,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19489682/

10-09 18:40