编译为空的虚拟 IEnumerable<T>

问题描述 投票:0回答:4
我正在创建一个基类,它有一个名为“GetBaseAddresses()”的

virtual

方法。它有一个返回类型 
IEnumerable<Uri>
。如果枚举,基类不会 
yield
 任何结果,但派生类可以选择重写该方法并返回所需数量的项目。

这是基本方法:

public virtual IEnumerable<Uri> GetBaseAddresses() { }

问题是,它无法编译。您

必须返回一个值,编译器才会满意。所以,因为我想要一个空结果,所以我就返回 null

,对吧?

public virtual IEnumerable<Uri> GetBaseAddresses() { return null; }

问题在于,如果有人对基类的实例执行

foreach

,他们将会崩溃,并出现“对象引用未设置...”的运行时错误

所以,回想一下

yield return

 关键字对 C# 编译器有一些魔力……我想出了这个编译器 hack(顺便说一下,它可以工作)。

public virtual IEnumerable<Uri> GetBaseAddresses() { if (false) { yield return new Uri(""); } }

奇怪的是,即使“if (false) { ... }”代码被完全编译掉 - 编译器对我满足“必须返回一个值”的要求感到满意,并且完全按照我想要的进行 - 也就是说,可以安全枚举的空结果集。

我的问题是 - 有没有办法在没有我的编译器技巧的情况下做到这一点?

c# ienumerable virtual yield-return
4个回答
10
投票
使用空数组,或者:

yield break; //end enumeration

从评论中提取 svick 的想法:

return Enumerable.Empty<Uri>();

这更快,因为

Enumerable.Empty

 总是返回一些空枚举的缓存的、预先分配的实例。


9
投票
只需在基本方法中返回一个空的枚举即可。

public virtual IEnumerable<Uri> GetBaseAddresses() { return Enumerable.Empty<Uri>(); }

或者如果您的目标是 .NET 框架的某个版本

< 3.5 return an empty List.


5
投票
内置数组支持 IEnumerable,因此您可以使用:

public virtual IEnumerable<Uri> GetBaseAddresses() { return new Uri[0]; }
    

0
投票
empty 方法不起作用的原因是编译器假设如果您在方法中不使用

yield

 关键字,那么您想要创建一个普通方法,而不是迭代器。这也是你的 
if (false)
 hack 起作用的原因。

要正确编写返回空集合的方法,您可以按照通常的方式返回空集合:

public virtual IEnumerable<Uri> GetBaseAddresses() { return Enumerable.Empty<Uri>(); }

或者你可以使用

yield break

:

public virtual IEnumerable<Uri> GetBaseAddresses() { yield break; }
    
© www.soinside.com 2019 - 2024. All rights reserved.