将单个项作为IEnumerable传递

15 浏览
0 Comments

将单个项作为IEnumerable传递

在C# 2.0的框架版本中,有一种常见的方式可以将类型为T的单个项目传递给期望IEnumerable参数的方法吗?\n目前我正在使用一个辅助方法(它是.Net 2.0的,所以我有一堆类似于LINQ的转换/投影辅助方法),但这似乎很愚蠢:\n

public static class IEnumerableExt
{
    // 用法:IEnumerableExt.FromSingleItem(someObject);
    public static IEnumerable FromSingleItem(T item)
    {
        yield return item; 
    }
}

\n另一种方式当然是创建和填充一个ListArray,并将其传递给IEnumerable。\n[编辑] 作为扩展方法,它可能被命名为:\n

public static class IEnumerableExt
{
    // 用法:someObject.SingleItemAsEnumerable();
    public static IEnumerable SingleItemAsEnumerable(this T item)
    {
        yield return item; 
    }
}

\n我是否遗漏了什么?\n[编辑2] 我们发现someObject.Yield()(如下面的评论中@Peter建议的)是这个扩展方法的最佳名称,主要是为了简洁,所以这里还有XML注释,如果有人想要使用:\n

public static class IEnumerableExt
{
    /// 
    /// 将此对象实例包装成由单个项目组成的IEnumerable<T>。
    /// 
    /// 对象的类型。
    /// 将被包装的实例。
    /// 由单个项目组成的IEnumerable<T>。
    public static IEnumerable Yield(this T item)
    {
        yield return item;
    }
}

0
0 Comments

问题:为什么会出现(Passing a single item as IEnumerable)这个问题,以及如何解决?

在讨论中,某些情况下了一个辅助方法作为解决方案,认为这是最干净的方法。如果传入一个列表或数组,那么不可信任的代码可能会将其强制转换并更改内容,在某些情况下导致奇怪的行为。虽然可以使用只读集合,但这可能需要更多的包装。有人认为这个解决方案非常简洁。

另外,某些情况下,如果传入的是一个数组,它怎么会被更改?可能可以将其强制转换为数组,然后将引用更改为其他内容,但这有什么好处呢?(不过我可能漏掉了什么...)

还某些情况下,假设你决定创建一个可枚举对象并传递给两个不同的方法...然后第一个方法将其强制转换为数组并更改内容。然后你将其作为参数传递给另一个方法,却不知道它的变化。我不是说这很可能发生,只是说当不需要可变性时,拥有可变性不如自然的不可变性简洁。

在问题讨论中,某些情况下了使用myDict.Keys.AsEnumerable()方法时遇到了问题。经过重命名扩展方法SingleItemAsEnumerable后,一切开始正常工作。问题是无法将IEnumerable<Dictionary<CheckBox,System.Tuple<int,int>>.KeyCollection>'转换为'IEnumerable<CheckBox>'。是否缺少一个强制转换?尽管可以暂时使用这个hack,但其他高级开发人员能找到更好的方法吗?

最后,某些情况下了MoreLINQ这个库,期望能在其中找到类似的解决方案,但没有找到。

问题的原因是传递单个项作为IEnumerable可能会导致不可预料的行为,因此需要某种解决方案。解决方案是创建一个辅助方法,将单个项包装为可枚举对象,以确保不可变性和更干净的代码。此外,还可以使用MoreLINQ库进行进一步的研究,以寻找类似的解决方案。

0
0 Comments

在C# 3.0中,你可以使用System.Linq.Enumerable类来解决这个问题。使用Enumerable.Repeat(item, 1)可以创建一个只包含你的item的新的IEnumerable。

然而,有人认为这种解决方法会使代码变得更难阅读。因为对一个单独的元素使用Repeat方法可能会让人感到困惑。

有人认为使用Repeat一次是可行的,这样做更简单,而且不需要担心添加额外的扩展方法,并确保所使用的命名空间被包含。

也某些情况下可以使用new[]{ item }来解决这个问题,他认为这是一个有趣的解决方法。

有人认为这个解决方法很好。

有人认为这个解决方法应该被接受。因为它易于阅读、简洁,并且在BCL中以单行代码实现,而不需要自定义扩展方法。

0
0 Comments

问题的出现原因:在调用一个方法时,如果方法的参数类型是IEnumerable,那么需要传递一个列表对象作为参数,即使列表中只有一个元素。

解决方法:可以将单个元素封装成一个列表对象,然后将该列表对象作为参数传递给方法。

代码示例:

IEnumerable method(IEnumerable items) {
    // 方法体
}
T item = ...; // 单个元素
var list = new[] { item }; // 将单个元素封装成列表对象
method(list); // 传递列表对象作为参数

这样就可以将单个元素作为参数传递给期望接收IEnumerable类型参数的方法了。

0