将单个实例对象作为IEnumerable返回

18

我有一个 foo 类的实例,并且希望将其作为 IEnumerable 返回。是否可以在不创建新列表等情况下完成?

也许可以尝试以下方法:

IEnumerable<foo>.fromInstance(foo)

2
可能是将单个项作为IEnumerable <T>传递的重复问题。 - nawfal
4个回答

21

选项:

  • 创建一个集合类的实例,如数组或列表。默认情况下,这将是可变的,如果这是您想要在API中传递的序列,则可能略微不方便。但是,您可以创建一个ReadOnlyCollection<T> 包装器来包装这样的集合。
  • 按照Botz3000的答案编写自己的迭代器块。
  • 使用LINQ中的Enumerable.Repeat(item, 1),如果您正在使用.NET 3.5。

最佳答案取决于用途。如果您仅仅需要调用另一个使用序列的方法,并且知道它不会被修改,我可能会使用数组。例如,为了调用另一个序列上的Concat方法,您可能希望使用:

var wholeList = regularList.Concat(new[] { finalValue });

我相信Concat不会改变数组本身的值,而且其他任何东西都不会看到对数组本身的引用。

如果你需要将序列返回给其他代码,并且不知道它可能会对序列做什么,我可能会使用Enumerable.Repeat


对于那些使用 Rx(http://msdn.microsoft.com/en-us/devlabs/ee794896)的人来说,另一个选项是 EnumerableEx.Return 方法。 - Konstantin Oznobihin
缺少最清晰的方式:new [] { item } - data
@data_smith:那不是“创建一个集合类的实例,比如数组或列表”所覆盖的吗? - Jon Skeet
@JonSkeet:因为它是一种包罗万象的短语(您列表中的第一项)。下面建议的 new[] { item } 应该在答案中是正确的,我个人认为。我个人不知道 VS 可以推断数组类型。但无论如何,这只是一个观点,我只是认为 new[]{} 更加直接明了。 - data
1
如果你调用的方法以 IEnumerable<T> 作为参数,那么可以安全地假设它不会改变序列吗?至少不会以任何使发送数组不安全的方式改变它吧? - Adrian Ratnapala
@AdrianRatnapala:不一定。它可以将参数转换为数组(有条件地)并对其进行改变。这实际上取决于您对所讨论的代码的信任程度。 - Jon Skeet

17

你可以这样做:

public IEnumerable<Foo> GetSingleFooAsEnumerable() { 
    yield return singleFoo;
}

我赞同这个回答;这种技术也适用于枚举特定的成员变量。 - vincent gravitas

14

最佳的惯用方法是使用类似于 new[] { foo } 的方式,它只创建一个由类型为 foo 声明的元素组成的一维数组。

唯一可能的缺点是数组不是不可变的,因此有人可以将您的 IEnumerable<T> 强制转换为 T[] 并在其中更改值。虽然这种情况相当不太可能发生,但我不会担心它。


简洁、简明、清晰。这应该放在顶部并被接受。+1 - data

0

IEnumerable 应该用于可以枚举的内容,因此将其用于单个实例似乎相当奇怪。如果您确实需要这样做,可以像这样完成。可能有更好的方法,但这应该能完成工作:

List<foo> myList = new List<foo>();
myList.Add( myInstanceOfFoo );
IEnumerable myEnumerable = myList.AsEnumerable();

无论你怎么看,实际上你正在尝试制作一个只有一个元素的列表,这样做其实没有必要把它变成一个列表。

4
将单个对象转换为IEnumerable可能有很多原因。例如,可能希望将其传递给期望IEnumerable的方法,或者用于模拟Maybe monad等。 - Konstantin Oznobihin
这在技术上是正确的,因此避免了我给出反对票。但是考虑到其他的答案,它看起来几乎是最差的。 - Marc L.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接