【问题标题】:How to implicitly cast custom IEnumerable in foreach?如何在 foreach 中隐式转换自定义 IEnumerable?
【发布时间】:2019-06-05 12:26:27
【问题描述】:

我希望foreach 循环中的var 隐式转换我的自定义IEnumerable 的项目。它在内部Dictionary 上循环,主要是一个包装器。我尝试了通用和非通用IEnumerable

我想了解在 foreach 循环中支持隐式转换需要什么。

public class Bewerbung : IEnumerable<KeyValuePair<string, string>>
{
        protected Dictionary<string, string> internDic = new Dictionary<string, string>();


        public IEnumerator GetEnumerator()
        {
            return internDic.GetEnumerator();
        }

        IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator()
        {
            return internDic.GetEnumerator() ;
        }
}
            var bewerbung = new Bewerbung();
            foreach (var testi in bewerbung)
            {

            }

testi 始终是一个对象,而不是 KeyValuePair,就像它应该的那样。

我知道我可以将显式转换用于实际用途,但我想了解我的方法有什么问题。其他IEnumerables 可以隐式转换,为什么这不适用于我的自定义类?

【问题讨论】:

    标签: c# casting ienumerable


    【解决方案1】:

    foreach 是一个有趣的野兽 - 它尽可能是鸭式的(意思是:如果存在 public {something} GetEnumerator() 方法,它实际上不需要 IEnumerable[&lt;T&gt;] API),在你的情况下,public方法是非通用方法。所以...反过来:

    IEnumerator IEnumerable.GetEnumerator()
    {
        return internDic.GetEnumerator();
    }
    
    public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
    {
        return internDic.GetEnumerator();
    }
    

    另请注意,将显式实现代理到public 是很常见的,以避免维护错误,即

    IEnumerator IEnumerable.GetEnumerator()
        => GetEnumerator();
    
    public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
        => internDic.GetEnumerator();
    

    如果您想对此进行优化,您甚至可以公开自定义字典枚举器:

    IEnumerator IEnumerable.GetEnumerator()
        => GetEnumerator();
    
    IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator()
        => GetEnumerator();
    
    public Dictionary<string, string>.Enumerator GetEnumerator()
        => internDic.GetEnumerator();
    

    【讨论】:

    • @MarcGravell,所以,我们可以从IEnumerable 继承Bewerbung,对吧?
    • @DmitryStepanov 你可以,但这将是一个坏主意 - LINQ - 只是好的实践等 - 期望IEnumerable&lt;T&gt;,而不仅仅是IEnumerable
    • @DmitryStepanov 但要明确一点:您无需实现 任何 接口即可使用foreach - 仅拥有GetEnumerator() 本身就足够了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 2020-03-29
    • 1970-01-01
    • 2017-02-06
    • 2014-04-19
    相关资源
    最近更新 更多