c# - 使用隐式 DictionaryEntry 迭代 IDictionary

标签 c# idictionary

考虑这段代码:

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 ...

最佳答案

Why cannot I type foreach(var vari in variables)?

好吧,你可以 - 但 vari 隐式属于 object 类型。

您碰巧知道迭代器中的每个条目都是一个 DictionaryEntry,但编译器不知道。据它所知,IDictionary 的迭代元素类型只是object。尽管 IDictionary.GetEnumerator 返回 IDictionaryEnumerator ,它仍然有一个 Current 属性,其类型为 object,而不是 DictionaryEntry

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

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

编辑:对于那些想了解如何声明 IDictionaryEnumerator 的人,这里有一个简短但完整的示例。请注意,这并没有在任何地方使用泛型,但是确实Main 中使用了 var,仍然有一个隐式类型为 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/

相关文章:

c# - 如何将字典列表转换为 IDictionary “C#”

c# - 二维数组。将所有值设置为特定值

c# - 以编程方式确定路径是否受限

c# - 将字符串数组转换为双数组的最快方法?

c# - IDictionary 如何在删除时获取已删除的项目值

c# - 将字典中的所有键转换为大写

c# - IDictionary 和 IReadOnlyDictionary 的扩展方法

c# - 编写嵌套方法的正确方法是什么?

c# - 如何让 WPF TextBlock 在异步设置 Text 属性的位置滚动?