15

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>か?

4

7 に答える 7

26

あなたは車輪を再発明しています。それはEnumerable.Selectが意図したものです。

@KeithS による編集:質問に答えるために、この出力が必要な場合は、Enumerable.Select をラップする拡張メソッドを定義できます。

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));
}
于 2012-05-29T12:43:11.023 に答える
15

テキストと値を抽出するには、パラメータとして指定した 2 つの関数を使用するだけです。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) };
}

次のように使用できます (2 つのラムダを指定する必要があります)。

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

ただし、次のように使用することもできますEnumerable.Select

var selectedItems = items.Select(x => new SelectListItem { Text = ..., Value = ... });
于 2012-05-29T12:43:39.947 に答える
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;
}

お勧めするかもしれませんが、Funcs は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)
        };
    }
}

ここに利回りのリファレンスがあります。結果を列挙可能な要素として返すことができ、列挙可能なものを(あなたに)見えないように構築します。

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

于 2012-05-29T12:41:03.810 に答える
4

私にとっては、水を得るために川を渡るようなものです。単に選択を使用しないのはなぜですか?

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();  
    }
于 2012-05-29T12:48:34.483 に答える
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) 
           };
}
于 2012-05-29T12:57:01.757 に答える
0

他のソリューションも同様に機能しますが、Martin Liversage のソリューションが最適な方法だと思います。

IEnumerable<SelectListItem> selectListItems = items.Select(x => 
    new SelectListItem 
        { 
            Text = x.TextProperty, 
            Value = x.ValueProperty 
        });
于 2012-05-29T14:17:26.523 に答える
0

拡張メソッドの本体内では、これら 2 つのパラメーターは単なるデリゲートであり、他の関数と同じように実行できます。

        selectList.Add(new SelectListItem() { Text = text(model), Value = value(model)});
于 2012-05-29T12:41:29.870 に答える