Есть ли общий способ передать один элемент типа T
методу, который ожидает параметр IEnumerable<T>
? Язык - C #, версия фреймворка 2.0.
В настоящее время я использую вспомогательный метод (это .Net 2.0, поэтому у меня есть целая куча вспомогательных методов приведения / проецирования, подобных LINQ), но это кажется глупым:
public static class IEnumerableExt
{
// usage: IEnumerableExt.FromSingleItem(someObject);
public static IEnumerable<T> FromSingleItem<T>(T item)
{
yield return item;
}
}
Другой способ, конечно, - создать и заполнить List<T>
или Array
и передать его вместо IEnumerable<T>
.
[Edit] В качестве метода расширения его можно назвать:
public static class IEnumerableExt
{
// usage: someObject.SingleItemAsEnumerable();
public static IEnumerable<T> SingleItemAsEnumerable<T>(this T item)
{
yield return item;
}
}
Я что-то упустил?
[Edit2] Мы обнаружили, что someObject.Yield()
(как @Peter предложил в комментариях ниже) - лучшее имя для этого метода расширения, в основном для краткости, поэтому здесь оно вместе с комментарием XML, если кто-то хочет возьми это:
public static class IEnumerableExt
{
/// <summary>
/// Wraps this object instance into an IEnumerable<T>
/// consisting of a single item.
/// </summary>
/// <typeparam name="T"> Type of the object. </typeparam>
/// <param name="item"> The instance that will be wrapped. </param>
/// <returns> An IEnumerable<T> consisting of a single item. </returns>
public static IEnumerable<T> Yield<T>(this T item)
{
yield return item;
}
}
if (item == null) yield break;
Теперь вы не можете передавать значение null, а также использовать (тривиальный) шаблон нулевого объекта дляIEnumerable
. (foreach (var x in xs)
отлично справляется с пустымxs
). Между прочим, эта функция является монадической единицей для монады списка, которая равнаIEnumerable<T>
, и, учитывая монадный праздник любви в Microsoft, я удивлен, что что-то подобное вообще отсутствует во фреймворке. - person Matt Enright   schedule 11.11.2009IEnumerableExt.Empty
, которое содержит только операторyield break;
внутри, просто чтобы избежать передачи null в качестве параметра моему методу одного элемента. Это также оставляет (маловероятный) вариант возврата одного нулевого значения изIEnumerable<T>
, если это необходимо. - person Groo   schedule 12.11.2009params
таким образом, который затрагивается некоторыми ответами и комментариями здесь и очень похож на ваш второй метод. Это определенно самая короткая функция, которую я когда-либо писал! - person Gert Arnold   schedule 08.10.2011AsEnumerable
, потому что встроенное расширение с таким именем уже существует. (КогдаT
реализуетIEnumerable
, например,string
.) - person Jon-Eric   schedule 13.08.2012item == null
никогда не возвращает false для типа значения, не означает, что вы не можете его использовать - это совершенно законный оператор с предполагаемой семантикой. - person Matt Enright   schedule 05.11.2012Yield
? Нет ничего лучше краткости. - person Philip Guin   schedule 19.11.2012left == null
, где left - это тип значения (так что условие тривиально ложно), что ничего не вредит и имеет смысл, когда тип неизвестен, а во-вторых, я думаю Хороший принцип - использовать нулевые объекты (например, пустую последовательность) вместо буквального нуля во имя надежности, когда что-то подобное существует. - person Matt Enright   schedule 27.09.2013left==null
чек. Это нарушает красоту кода и препятствует тому, чтобы код был более гибким - что, если однажды вам понадобится сгенерировать синглтон с чем-то, что может быть нулевым? Я имею в виду, чтоnew T[] { null }
- это не то же самое, чтоnew T[] {}
, и когда-нибудь вам может потребоваться различить их. - person Earth Engine   schedule 24.03.2014Once
? - person Yurii N.   schedule 08.02.2018IEnumerable<T>
. Тот факт, чтоYield
иyield
- одно и то же слово, потому что они имеют одинаковую семантику; это не имеет ничего общего с реализацией. - person Jim Balter   schedule 29.11.2018int?
, то естьNullable<int>
. Это одна из многих недоразумений и ошибок в комментариях здесь. - person Jim Balter   schedule 29.11.2018new T[] { item }
у меня сработало. Я думаю, что case T будет именем моего класса, откуда я его вызываю, а item - экземпляром этого класса. - person Atta H.   schedule 29.04.2019