如何将类型为T的单个值转换为IEnumerable<T>?

14
我希望你能为这个做法提供一个良好的标准方式,然而每次我参与的项目都需要编写自己的Unity方法或创建内联数组等。

(我希望这个问题很快就会被关闭,因为已经有一些关于这个问题的优秀答案了)


https://dev59.com/Am445IYBdhLWcg3wmLhe - Jamie Dixon
这里描述了一个扩展方法,它使用yield返回值:https://dev59.com/OnI-5IYBdhLWcg3w-96b - BoltClock
4个回答

20

一种简单的方法:

var singleElementSequence = Enumerable.Repeat(value, 1);

或者您可以在未受限制的泛型类型上编写自己的扩展方法(诚然,这通常是一个不好的主意...请谨慎使用):

public static IEnumerable<T> ToSingleElementSequence<T>(this T item)
{
    yield return item;
}

用法:

IEnumerable<String> sequence = "foo".ToSingleElementSequence();

我认为我会更倾向于使用Enumerable.Repeat :)

3
我在“文学编程”中遇到了一个问题,涉及到“滥用”Repeat。Repeat所表达的与代码尝试达到的恰恰相反:它试图“不重复”任何项目 :) - sehe
1
我不认为使用 yield 是个好主意。这会导致编译器为仅有一个元素的情况生成全新的枚举器实现和相关状态机。只需使用 return new[] { item }; 即可避免所有繁重的代码生成,而且不会产生任何额外的分配。 - Sven
3
另一方面,它会生成可变的东西。你愿意多少依赖于人们不将其强制转换回数组并潜在地进行更改?@Sven - Jon Skeet
1
你可以妥协并显式实现IEnumerable <T>,从而避免状态机和易于访问的底层数组。然而,在正常情况下,我真的不认为这样做有太多好处,但是如果我为广泛使用的框架编写此函数,我可能会考虑这样的妥协以获取潜在微小的效率提升。 - Brian
1
对于非受限泛型类型的扩展方法(诚然,这通常是一个坏主意……请慎用)——这么做不好是因为它会附着在 任何东西 上并过度暴露,或者说还有其他更具体的问题吗? - ruffin
显示剩余6条评论

11
最短的方式是:
new T[]{value}

6
甚至可以使用new [] {value},在此情况下可以省略类型。请注意,我会尽力使翻译流畅易懂,但不会更改原意或添加解释。 - gofal3

5

编辑:我想提到一些我在LINQ中最喜欢的设备:

 internal static IEnumerable<T> Concat<T>(params T[] objs)
 {
      return objs;
 }

 internal static IEnumerable<T> Concat<T>(this IEnumerable<T> e, params T[] objs)
 {
      return e.Concat(objs);
 }

 internal static IEnumerable<T> Concat<T>(this IEnumerable<T> e, params IEnumerable<T>[] seqs)
 {
      foreach (T t in e) yield return t;
      foreach (var seq in seqs)
           foreach (T t in seq) yield return t;
 }

 // this allows you to
 var e1 = Concat(1,2,3);       // 1,2,3
 var e2 = e1.Concat(4,5,6);    // 1,2,3,4,5,6,
 var e3 = e2.Concat(e2, e1, Concat(42)); // 1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,42

非常方便以任何方式定义文字列表,形式多样。
另一种简单的方式:
 IEnumerable<int> = new [] {42};

另一种简单的方法是:
 internal static IEnumerable<T> Enumerable<T>(this T obj)
 {
      yield return obj;
 }

 //
 var enumerable = 42.Enumerable();

4
你可以定义自己的扩展方法:
public static class IEnumerableExt
{
    // usage: someObject.AsEnumerable();
    public static IEnumerable<T> AsEnumerable<T>(this T item)
    {
        yield return item; 
    }
}

.NET框架中没有执行此任务的功能。

例如,上面Jon的回答? - Mitch Wheat
好的... 没有专门为此目的设计的方法。您可以使用 Repeat 来实现这一点 - 我同意。 - ColinE

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