IEnumerable扩展

时间:2012-05-29 12:38:02

标签: c# .net extension-methods ienumerable

我想制作一个IEnumerable<TSource>扩展程序,可将自身转换为IEnumerable<SelectListItem>。到目前为止,我一直试图这样做:

    public static 
      IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(this 
      IEnumerable<TSource> enumerable, Func<TSource, TKey> text, 
                                       Func<TSource, TKey> value)
    {
        List<SelectListItem> selectList = new List<SelectListItem>();

        foreach (TSource model in enumerable)
            selectList.Add(new SelectListItem() { Text = ?, Value = ?});

        return selectList;
    }

这是正确的做法吗?如果是这样,我如何从Func<TSource, TKey>

中的适当值中绘制值

7 个答案:

答案 0 :(得分:26)

你正在重新发明轮子。这是Enumerable.Select的目的。

编辑@KeithS:要回答这个问题,如果你想要这个输出,你可以定义一个包装Enumerable的扩展方法。选择:

public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
  this IEnumerable<TSource> enumerable,
  Func<TSource, string> text,
  Func<TSource, string> value)
{ 
  return enumerable.Select(x=>new SelectListItem{Text=text(x), Value=value(x));
}

答案 1 :(得分:15)

你走在正确的道路上。

Funcs是存储在变量中的方法,并且像普通方法一样被调用。

public static IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(
    this IEnumerable<TSource> enumerable,
    Func<TSource, TKey> text,
    Func<TSource, TKey> value)
{
    List<SelectListItem> selectList = new List<SelectListItem>();

    foreach (TSource model in enumerable)
    {
        selectList.Add(new SelectListItem()
        {
            Text = text(model),
            Value = value(model)
        });
    }

    return selectList;
}

如果我建议,您的Func应该是Func<TSource, string>,因为文本和值是SelectListItem中的字符串。

编辑想到这个......

此外,您不必创建内部列表,而是可以执行 yield return 。以下是我的方法的“优化”版本。

public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
    this IEnumerable<TSource> enumerable,
    Func<TSource, string> text,
    Func<TSource, string> value)
{
    foreach (TSource model in enumerable)
    {
        yield return new SelectListItem()
        {
            Text = text(model),
            Value = value(model)
        };
    }
}

以下是 yeild return 的参考资料。它允许您将结果作为可枚举元素返回,以隐形方式构建您的可枚举(对您而言)。

http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

答案 2 :(得分:15)

您只需使用您提供的两个函数作为参数来提取文本和值。假设text和value都是字符串,则不需要TKey类型参数。并且无需在扩展方法中创建列表。使用yield return的迭代器块更可取,并且如何构建LINQ中类似的扩展方法。

public static IEnumerable<SelectListItem> ToSelectItemList<TSource>(
  this IEnumerable<TSource> enumerable,
  Func<TSource, string> text,
  Func<TSource, string> value)
{ 
  foreach (TSource model in enumerable) 
    yield return new SelectListItem { Text = text(model), Value = value(model) };
}

你可以像这样使用它(你需要提供两个lambdas):

var selectedItems = items.ToSelecListItem(x => ..., x => ...);

但是,您也可以使用Enumerable.Select

var selectedItems = items.Select(x => new SelectListItem { Text = ..., Value = ... });

答案 3 :(得分:4)

对我来说,似乎过河要水。为什么不简单地使用select?

enumerable.Select(item => 
                    new SelectListItem{
                          Text = item.SomeProperty, 
                           Value item.SomeOtherProperty
                    }).ToList();

如果你真的想要一个方法,那么你可以这样做:

public static 
      IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(this 
      IEnumerable<TSource> enumerable, Func<TSource, TKey> text, 
                                       Func<TSource, TKey> value)
    {
        return (from item in enumerable
                select new SelectListItem{
                      Text = text(item),
                      Value = value(item)
                }).ToList();  
    }

答案 4 :(得分:4)

实现你想要的LINQ方式是:

public static IEnumerable<SelectListItem> ToSelectItemList<TSource, TKey>(
    this IEnumerable<TSource> enumerable, 
    Func<TSource, TKey> textSelector, 
    Func<TSource, TKey> valueSelector)
{
    return from model in enumerable
           select new SelectListItem 
           { 
               Text = textSelector(model), 
               Value = valueSelector(model) 
           };
}

答案 5 :(得分:0)

在扩展方法的主体中,这两个参数只是委托,您可以像任何其他函数一样运行它们:

        selectList.Add(new SelectListItem() { Text = text(model), Value = value(model)});

答案 6 :(得分:0)

其他解决方案也有效,但我认为Martin Liversage的解决方案是最好的方法:

IEnumerable<SelectListItem> selectListItems = items.Select(x => 
    new SelectListItem 
        { 
            Text = x.TextProperty, 
            Value = x.ValueProperty 
        });