列表中的收益项

时间:2016-02-09 08:26:31

标签: c# yield

在我的应用程序中,只有List<MyItem>只有一个getter:

public List<MyItem> myList
{
    get
    {
         MyHost.GetItemFromID(_i1); //this may be a long operation
         MyHost.GetItemFromID(_i2);
         MyHost.GetItemFromID(_i3);
         MyHost.GetItemFromID(_i4);
         MyHost.GetItemFromID(_i5);
    }
}

此列表有时需要整体检索,有时只需要访问某些项目:即myList[3]。有没有办法不建立整个列表,因为我只需要第四项?

4 个答案:

答案 0 :(得分:5)

你可以用一个类包装列表,比如说'myListContainer&#39;并且超载它的&#39; []&#39;运算符,以便您可以执行以下操作:

myListContainer[3] 

将调用

 MyHost.GetItemFromID(_i3);

并返回所需的列表项。

如果需要,我会添加一个完整的例子

修改

 public class myListContainer
{

    public MyItem this[int i]
    {
        get
        {
            return MyHost.GetItemFromID(i);
        }

    }
}

并添加方法以获取整个列表。

答案 1 :(得分:3)

您可以返回IEnumerable<MyItem>并使用yield return

public IEnumerable<MyItem> MyItems
{
    get
    {
        yield return MyHost.GetItemFromID(_i1); //this may be a long operation
        yield return MyHost.GetItemFromID(_i2);
        yield return MyHost.GetItemFromID(_i3);
        yield return MyHost.GetItemFromID(_i4);
        yield return MyHost.GetItemFromID(_i5);
    }
}

然后它使用延迟执行,你可以写:

var fourItems = MyItems.Take(4).ToList();

请注意,如果订单不重要,那么更改执行顺序可能是一个好主意,只有GetItemFromID的第一次调用比其他调用花费更多时间:

yield return MyHost.GetItemFromID(_i2);
yield return MyHost.GetItemFromID(_i3);
yield return MyHost.GetItemFromID(_i4);
yield return MyHost.GetItemFromID(_i5);
yield return MyHost.GetItemFromID(_i1); //this may be a long operation

我想我误解了这个要求。我已经阅读&#34;有时我只需要第四项&#34; &#34;只需要四项&#34;

所以你可以使用我的aproach但ElementAt

MyItem fourthItem = MyItems.ElementAt(3);

如果你不知道第四次使用ElementAtOrdefault是不是。

答案 2 :(得分:1)

注意:

这假定为第4项&#39;你的意思是一个序数,而不是实际的身份。

提前构建地图并仅返回您想要的项目。

List<int> map = new List<int> 
{ 
    _i1,
    _i2, 
    _i3, 
    _i4, 
    _i5,     
};

public IEnumerable<MyItem> myList(params int[] indices)
{
    if (!indices.Any())
        return map.Select(MyHost.GetItemFromID);

    return indices.Select(i => MyHost.GetItemFromID(map[i]));
}

// so you call 
myList(); // for all items; decide on this API, may be separate to two methods?
myList(0); // or
myList(4); // or
myList(1, 3); // all loaded only on demand

如果您想要更多地控制索引,请使用字典。理想情况下,出于某种原因,看起来你应该一次性将所有ID传递给DB,如果是这种情况,SQL会直接处理它。

答案 3 :(得分:1)

我不知道你的_i1等键的类型是什么,但我们假设它们是整数。然后你可以这样做:

public IEnumerable<MyItem> GetItems(params int[] keys)
{
    return keys.Select(key => MyHost.GetItemFromID(key));
}

您可以这样称呼:

var myItems = GetItems(_i2, _i3, _i5).ToList();

var myItems = GetItems(_i3).ToArray();

等等。

注意:如果您只想要返回一个列表,您可以在GetItems()内部进行转换:

public List<MyItem> GetItems(params int[] keys)
{
    return keys.Select(key => MyHost.GetItemFromID(key)).ToList();
}

但这种方法需要一种方法而不是一种属性。