Это потому, что она упаковывает вашу задачу Callable
как RunnableFuture
перед очередью или выполнением.
Этот RunnableFuture
реализует интерфейс Runnable
(в дополнение к Future
).
Таким образом, все вызовы могут быть поставлены в очередь и выполнены без каких-либо проблем.
Посмотрите на AbstractExecutorService
источник для получения дополнительной информации.
Один из вариантов - перегрузить его самостоятельно:
public static IEnumerable<T> Union<T>(this IEnumerable<T> source, T item)
{
return source.Union(Enumerable.Repeat(item, 1));
}
Рассмотрите возможность использования еще более гибкого подхода:
public static IEnumerable<T> Union<T>(this IEnumerable<T> source, params T[] items)
{
return source.Union((IEnumerable<T>)items);
}
Работает как для одного, так и для нескольких предметов. Вы также можете принять нулевые source
значения:
public static IEnumerable<T> Union<T>(this IEnumerable<T> source, params T[] items)
{
return source != null ? source.Union((IEnumerable<T>)items) : items;
}
Новый способ сделать это, поддерживаемый в .NET Core и .NET Framework начиная с версии 4.7.1, использует метод расширения Append
.
Это сделает ваш код таким же простым и элегантным, как
var sandwich = top.Append(filling).Union(bottom);
. В моем коде обычно есть следующее:
public static IEnumerable<T> EmitFromEnum<T>(this T item)
{
yield return item;
}
Хотя не так удобно вызывать col.Union (obj.EmitFromEnum ());
как col.Union (obj)
это означает, что этот единственный метод расширения охватывает все другие случаи, когда мне может понадобиться такое перечисление с одним элементом.
Обновление: с .NET Core теперь вы можете использовать .Append ()
или .Prepend ()
, чтобы добавить один элемент в перечислимое. Реализация оптимизирована, чтобы избежать создания слишком большого количества реализаций IEnumerator
за кулисами.