C# 延迟检索用作IEnumerable的数组

C# 延迟检索用作IEnumerable的数组,c#,C#,我可以访问一个公开T数组的API,即有一个签名 T[] Get(); 我正在创建一个API,它在Ts上执行计算并生成T2。对Get()的每次调用都很昂贵,从T到T2的每次投影都很昂贵。我可能不需要所有的T2s,因此我想公开: IEnumerable<T2> GetProjected(); 你可能知道我要说什么了。如何公开一个IEnumerable,而不立即调用Get()?是否必须实现自定义的IEnumerator和IEnumerable对?使用迭代器方法: public IEn

我可以访问一个公开
T
数组的API,即有一个签名

T[] Get();
我正在创建一个API,它在
T
s上执行计算并生成
T2
。对
Get()
的每次调用都很昂贵,从
T
T2
的每次投影都很昂贵。我可能不需要所有的
T2
s,因此我想公开:

IEnumerable<T2> GetProjected(); 

你可能知道我要说什么了。如何公开一个
IEnumerable
,而不立即调用
Get()
?是否必须实现自定义的
IEnumerator
IEnumerable
对?

使用迭代器方法:

public IEnumerable<T2> GetProjected()
{   
   var results = api.Get()
        .Select(t => ProjectToT2(t));

   foreach(var x in results) 
   {
        yield return x;
   }
}
public IEnumerable GetProjected()
{   
var results=api.Get()
。选择(t=>ProjectToT2(t));
foreach(结果中的var x)
{
收益率x;
}
}

由于
get()
的签名,您无法在一个完整的块中绕过正在检索的数组,但这样,只有当您枚举
GetProjected()
的结果时,才会调用它,例如,如果您对它调用
ToArray()
,而不是使用
Select()
其中
使用迭代器方法:

public IEnumerable<T2> GetProjected()
{   
   var results = api.Get()
        .Select(t => ProjectToT2(t));

   foreach(var x in results) 
   {
        yield return x;
   }
}
public IEnumerable GetProjected()
{   
var results=api.Get()
。选择(t=>ProjectToT2(t));
foreach(结果中的var x)
{
收益率x;
}
}

由于
get()
的签名,您无法在一个完整的块中绕过正在检索的数组,但这样,只有当您枚举
GetProjected()
的结果时,才会调用它,例如,如果您对它调用
ToArray()
,而不是使用
Select()
Where

这仍然是立即评估
懒惰的问题所在。@John OP问:“如何公开
IEnumerable
而不立即调用
Get()
?”这是答案。(我并不是说这样做有很多好处——没有足够的背景来判断。)@MoB。因为OP没有定义
Get()
,所以我一直在想,它已经返回了一个
IEnumerable
。很抱歉这是漫长的一天@不,它不会立即执行
Get()
。试试看。@AlexanderHøst不,莫是对的。在您开始迭代之前,它不应该执行
Get()
。这仍然是在立即评估
惰性的
,这就是问题所在。@John OP问:“如何公开
IEnumerable
,而不立即调用
Get()
?”这就是答案。(我并不是说这样做有很多好处——没有足够的背景来判断。)@MoB。因为OP没有定义
Get()
,所以我一直在想,它已经返回了一个
IEnumerable
。很抱歉这是漫长的一天@不,它不会立即执行
Get()
。试试看。@AlexanderHøst不,莫是对的。在您开始迭代之前,它不应该执行
Get()
。请解释为什么要这样做。是否要使IEnumerable准备好以后进行枚举,然后才调用Get()?使它成为迭代器方法或操作?是的-我希望它在以后可以用于枚举,并且我不希望消费者在调用
GetProjected
时担心正在计算任何内容。这是一个原因。另一个原因是,整个工作是可以取消的,这可能发生在中间位置。我意识到这很奇怪,但我真的觉得作为消费者,您应该能够相信检索
IEnumerable
不会导致大量昂贵的计算。@general它没有被枚举。它是可枚举的。仅仅因为我有一些可枚举的东西,并不意味着我马上就想枚举它。“我真的觉得作为消费者,你应该能够相信检索IEnumerable不会导致大量昂贵的评估”——检索或构建它,不是这样的。枚举它。您可以构建最复杂的实体框架查询,只要您不枚举结果,数据库就不会被命中。对于您的代码来说,这是不正确的,因为它调用了
Get()
。反编译
Get
并重写它以返回
IEnumerable
请解释为什么要这样做。是否要使IEnumerable准备好以后进行枚举,然后才调用Get()?使它成为迭代器方法或操作?是的-我希望它在以后可以用于枚举,并且我不希望消费者在调用
GetProjected
时担心正在计算任何内容。这是一个原因。另一个原因是,整个工作是可以取消的,这可能发生在中间位置。我意识到这很奇怪,但我真的觉得作为消费者,您应该能够相信检索
IEnumerable
不会导致大量昂贵的计算。@general它没有被枚举。它是可枚举的。仅仅因为我有一些可枚举的东西,并不意味着我马上就想枚举它。“我真的觉得作为消费者,你应该能够相信检索IEnumerable不会导致大量昂贵的评估”——检索或构建它,不是这样的。枚举它。您可以构建最复杂的实体框架查询,只要您不枚举结果,数据库就不会被命中。对于您的代码,这是不正确的,因为它调用
Get()
。反编译
Get
并重写它以返回
IEnumerable