C# 列表中的屈服项

C# 列表中的屈服项,c#,yield,C#,Yield,在我的应用程序中,有一个仅带getter的列表: public List<MyItem> myList { get { MyHost.GetItemFromID(_i1); //this may be a long operation MyHost.GetItemFromID(_i2); MyHost.GetItemFromID(_i3); MyHost.GetItemFromID(_i4);

在我的应用程序中,有一个仅带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
{
得到
{
MyHost.GetItemFromID(_i1);//这可能是一个很长的操作
MyHost.GetItemFromID(i2);
MyHost.GetItemFromID(_i3);
MyHost.GetItemFromID(i4);
MyHost.GetItemFromID(_i5);
}
}

此列表有时需要作为一个整体进行检索,而其他时候只需要访问某些项目:即
myList[3]
。有没有办法不构建整个列表,因为我只需要第四项?

您可以返回
IEnumerable
并使用:

请注意,如果顺序无关紧要,并且只有第一次调用
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

我想我误解了这个要求。我把“有时我只需要第四项”读作“只需要四项”

因此,您可以使用我的aproach,但要使用
元素at

MyItem fourthItem = MyItems.ElementAt(3);

如果您不知道是否有第四个用法
ElementAtOrdefault

您可以用一个类来包装列表,比如说“myListContainer”,并重载其“[]”操作符,这样您就可以执行以下操作:

myListContainer[3] 
var myItems = GetItems(_i2, _i3, _i5).ToList();
哪个将调用该调用

 MyHost.GetItemFromID(_i3);
并返回所需的列表项

如果需要,我将添加一个完整的示例

编辑

 public class myListContainer
{

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

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

注意: 这假设“第四项”是指序号,而不是实际id本身。
提前建立一张地图,只返回你想要的物品

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
列表映射=新列表
{ 
_i1,
_i2,
_i3,
_i4,
_i5,
};
公共IEnumerable myList(参数int[]索引)
{
如果(!index.Any())
返回map.Select(MyHost.GetItemFromID);
返回索引。选择(i=>MyHost.GetItemFromID(map[i]);
}
//所以你打电话
myList();//适用于所有项目;决定这个API,可以分为两种方法吗?
myList(0);//或
myList(4);//或
myList(1,3);//全部仅按需加载

如果您想对索引进行更多控制,请使用字典。理想情况下,出于某种原因,您应该一次性将所有ID传递给DB,如果是这样的话,SQL直接处理它。

我不知道
\u i1
等的密钥是什么类型的,但让我们假设它们是INT。然后你可以这样做:

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

等等

注意:如果您只希望返回列表,则可以在
GetItems()
本身中进行转换:

public List<MyItem> GetItems(params int[] keys)
{
    return keys.Select(key => MyHost.GetItemFromID(key)).ToList();
}
公共列表GetItems(参数int[]键)
{
return keys.Select(key=>MyHost.GetItemFromID(key)).ToList();
}

不过,这种方法需要方法而不是属性。

这很好。这假设传递的是实际的id,应该转到
GetItemFromID
函数。从OP上看不太明显。@nawfal同意-可能需要OP的澄清。这仍然需要加载客户不感兴趣的不需要的ID。@nawfal:你是对的,我误解了“有时我只需要第四项”。我把它读作“只需要四个项目”ElementAt在索引之前不会仍然遍历所有项目吗?换句话说,您的方法在传递的参数之前运行ID的GetFromID调用。@这不是OP后面的内容。虽然LINQ的代码看起来很酷;)@nawfal:true,它仍然需要调用all
GetItemFromID
。所以我个人更喜欢barakcaf的MyListContainer类apporach。
var myItems = GetItems(_i2, _i3, _i5).ToList();
var myItems = GetItems(_i3).ToArray();
public List<MyItem> GetItems(params int[] keys)
{
    return keys.Select(key => MyHost.GetItemFromID(key)).ToList();
}