【问题标题】:List Generic GetEnumerator Cast To An Interface Fails将通用 GetEnumerator 列表转换为接口失败
【发布时间】:2013-04-20 22:19:41
【问题描述】:

GetEnumerator 强制转换为接口失败
没有编译错误
消息索引无穷大的运行时失败
如果我直接使用没有接口的 struct Word1252 它可以工作

namespace WordEnumerable
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            WordEnum wordEnum = new WordEnum();
            Debug.WriteLine(wordEnum[0].GetType().ToString());
            Debug.WriteLine(wordEnum[0].Value);
            Debug.WriteLine(wordEnum.Count.ToString());
            foreach (iWord w in wordEnum)  // fails here
            {
            }
        }
    }
}
public interface iWord
{
    Int32 Key { get; }
    String Value { get; }
}
public class WordEnum : IEnumerable<iWord>
{
    private static List<Word1252> words1252 = new List<Word1252>();
    IEnumerator<iWord> IEnumerable<iWord>.GetEnumerator()
    {
        return ((IEnumerable<iWord>)words1252).GetEnumerator();
    }
    public struct Word1252 : iWord
    {
        public UInt64 packed;
        public Int32 Key   { get { return (Int32)((packed >> 27) & ((1 << 25) - 1)); } }
        public Byte Length { get { return (Byte) ((packed >> 59) & ((1 <<  5) - 1)); } }
        public String Value { get { return Key.ToString(); } }
        public Word1252(UInt64 Packed) { packed = Packed; }
    }

【问题讨论】:

    标签: c# .net interface enumerator


    【解决方案1】:

    简而言之就是upcastingIEnumerable&lt;Word1252&gt;IEnumerable&lt;IWord&gt;

    这需要covariance 才能工作。

    即使 IEnumerable 被标记为 out(协变)
    协变不适用于“值类型” - 即您拥有的结构 接口已定义。

    例如看……

    Is this a covariance bug in C# 4?
    (或有点不同,但归结为同一个问题)
    Why cannot IEnumerable<struct> be cast as IEnumerable<object>?

    要解决,您只需定义您的列表,如

    private static List<iWord> words1252 = new List<iWord>();  
    

    或者像这样定义你的枚举器:

    IEnumerator<iWord> IEnumerable<iWord>.GetEnumerator()
    {
        foreach (var word in words1252)
            yield return word;
    }
    

    【讨论】:

    • 他们都工作了,谢谢。使用私有静态 List words1252 = new List();我不得不将内部内容转换为 Word1252,但我会接受的。你知道 foreach 是否有性能损失吗?如果不是,我宁愿使用它。
    • 不客气。 foreach 更好我同意。那里没有性能影响(或最多有一些额外的操作)-它正在“屈服”-所以它基本上与原始“枚举器”做相同的事情-这是“枚举器”中已知且公认的“铸造”方法(即当您需要退回不同的物品 - 但无法投射时)
    猜你喜欢
    • 2014-11-30
    • 1970-01-01
    • 2011-01-01
    • 2019-01-11
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2011-11-26
    相关资源
    最近更新 更多