C# - Yield给出了一个不可用的类型

时间:2009-12-28 23:34:26

标签: c# wpf ienumerable yield

我有一个类和一组IEnumerables正在使用这个类给我列表中的列表。 (有关详细信息,请参阅此question的答案。)

以下是代码:

public IEnumerable<IEnumerable<WorkItemColumn>> EnumerateResultSet(WorkItemCollection queryResults)//DisplayFieldList displayFieldList)
{
    foreach (WorkItem workItem in queryResults)
    {
        yield return EnumerateColumns(queryResults.DisplayFields, workItem);   
    }
}

public IEnumerable<WorkItemColumn> EnumerateColumns(DisplayFieldList resultSet, WorkItem workItem)
{
    foreach (FieldDefinition column in resultSet)
        yield return new WorkItemColumn { Name = column.Name, Value = workItem[column.Name], WorkItemForColumn = workItem};
}

上课:

public class WorkItemColumn
{
    public string Name { get; set; }
    public object Value { get; set; }
    public WorkItem WorkItemForColumn { get; set; }
}

我将此结果设置为ListBox的ItemsSource

Form.QueryResultListSource = EnumerateResultSet(queryResults);

当我尝试捕获此列表框的事件时,问题就出现了:

public void QueryResultsSelectionChanged(SelectionChangedEventArgs e)
{
                                                   +-----------------+
                                                   v                 | 
    foreach (WorkItemColumn workItemColumn in e.AddedItems)          |
    {                                                                |
        AddWorkItemToPad(workItemColumn.WorkItemForColumn);          |
    }                                                +---------------|
                                                     |               |
                                                     v               |    
    foreach (WorkItemColumn workItemColumn in e.RemovedItems)        |
    {                                                                |
        RemoveWorkItemFromPad(workItemColumn.WorkItemForColumn);     |
    }                                                                |
                                                                     |    
}                                                                    |
                                                                     |
These items are where the problem is --------------------------------+

当我在调试时检查e.AddedItems [0]并且它的类型是EnumerateColumns。

当我尝试转换为该类型时,Visual Studio说(可以理解)EnumerateColumns是一个方法但是像类型一样使用。

那么,我怎么能按类型引用它,这样我就可以做一个foreach循环并得到它里面的东西?


这是我根据答案更新的代码:

public void QueryResultsSelectionChanged(SelectionChangedEventArgs e)
{
    foreach (IEnumerable<WorkItemColumn> workItemColumns in e.AddedItems)
    {
        if (workItemColumns.Count() > 0)
            AddWorkItemToPad(workItemColumns.First().WorkItemForColumn);                
    }

    foreach (IEnumerable<WorkItemColumn> workItemColumns in e.RemovedItems)
    {
        if (workItemColumns.Count() > 0)
            RemoveWorkItemFromPad(workItemColumns.First().WorkItemForColumn);    
    }
}

4 个答案:

答案 0 :(得分:2)

问题是你的第一个方法并没有产生第一个给出的每个结果 - 它产生了可枚举的本身。迭代器的编译器生成类型的类型 - 但重要的是,实现 IEnumerable<WorkItemColumn>

如果您愿意,可以将每个项目投放到IEnumerable<WorkItemColumn> - 但是您在QueryResultsSelectionChanged中尝试做的事情并不是很清楚。您可能想要这样做:

foreach (IEnumerable<WorkItemColumn> workItemColumns in e.AddedItems)
{                                                   
    foreach(WorkItemColumn workItemColumn in workItemColumns)
    {
        AddWorkItemToPad(workItemColumn.WorkItemForColumn); 
    }
}
等等......或者你可能没有。如果不知道你真正想要做什么,说这很棘手。无论如何,它的关键在于您目前正在尝试将序列项目视为单个项目。不要那样做:)

答案 1 :(得分:1)

e.AddedItems[0]是编译器生成的隐藏迭代器类型的实例,您不能直接使用它。
但是,它实现了IEnumerable<WorkItemColumn>,因此您可以通过该接口使用它。

换句话说:

foreach (IEnumerable<WorkItemColumn> colSet in e.RemovedItems)        
    foreah(WorkItemColumn workItemColumn in colSet)
        RemoveWorkItemFromPad(workItemColumn.WorkItemForColumn);     

答案 2 :(得分:1)

尽管使用迭代器可能不是解决此问题的最佳方法,但您可以通过将枚举存储在数组中来避免遇到的问题:

using System.Linq;
...
Form.QueryResultListSource = EnumerateResultSet(queryResults).ToArray();

将您的EnumerateResultSet更改为:

public IEnumerable<WorkItemColumn[]> EnumerateResultSet(WorkItemCollection queryResults)//DisplayFieldList displayFieldList) 
{ 
    foreach (WorkItem workItem in queryResults) 
    { 
        yield return EnumerateColumns(queryResults.DisplayFields, workItem).ToArray();    
    } 
} 

正如其他人所说,使用yield关键字,您实际上会返回一个知道如何迭代您想要枚举的项的函数。但是,将数据源设置为此枚举不会简单地执行一次并存储结果。通过使用迭代器,您可能会遇到很多性能问题,因为只要需要使用结果,迭代就需要重新执行。

答案 3 :(得分:0)

为了完整起见,您确实应该包含AddedItemsRemovedItems的相关代码。

尽管如此,使用完全限定的形式(包括名称空间包含)来转换具有类型名称的对象。这将使它绑定到类型而不是方法签名,因为该方法在类型级别不可用,但子类型将可用。