我正在尝试做这样的事情:
image.Layers
有时候,我只想要一个不包括Parent
层的所有层的IEnumerable<Layer>
,可以这样做:
image.Layers.With(image.ParentLayer);
因为与通常使用的image.Layers
相比,它仅在少数地方使用。这就是为什么我不想再创建另一个返回Parent
层的属性。
我正在尝试做这样的事情:
image.Layers
有时候,我只想要一个不包括Parent
层的所有层的IEnumerable<Layer>
,可以这样做:
image.Layers.With(image.ParentLayer);
因为与通常使用的image.Layers
相比,它仅在少数地方使用。这就是为什么我不想再创建另一个返回Parent
层的属性。
一种方法是将该项(例如数组)创建为单例序列,然后使用Concat
将其连接到原始序列中:
image.Layers.Concat(new[] { image.ParentLayer } )
Append
(或类似的)扩展方法,例如此处列出的一个,它将使您可以执行以下操作:image.Layers.Append(image.ParentLayer)
.NET Core 更新(根据下面的“最佳”答案):
Append
andPrepend
have now been added to the .NET Standard framework, so you no longer need to write your own. Simply do this:image.Layers.Append(image.ParentLayer)
Append
和Prepend
现已添加到.NET Standard框架中,因此您不再需要编写自己的代码。只需执行以下操作:
image.Layers.Append(image.ParentLayer)
请参见.Net Standard 2.0中有哪些在.Net Framework 4.6.1中不存在的43个API?,以获取新功能清单。
编辑
正如@cpb所正确提到的:
现在附加和前置已经默认提供。
(源代码)微软还决定实现一种在开头或结尾添加项目的方法。他们创建了一个AppendPrepend1Iterator类,它具有一些优化(例如,如果原始基础集合是ICollection,则获取计数)
出于历史原因,我将保留我的答案。
已经给出了许多不同的实现方式。
我的看起来有点不同(但效果一样好)
此外,我发现控制顺序也很实用。因此,通常我还有一个ConcatTo方法,在前面放置新元素。
public static class Utility
{
/// <summary>
/// Adds the specified element at the end of the IEnummerable.
/// </summary>
/// <typeparam name="T">The type of elements the IEnumerable contans.</typeparam>
/// <param name="target">The target.</param>
/// <param name="item">The item to be concatenated.</param>
/// <returns>An IEnumerable, enumerating first the items in the existing enumerable</returns>
public static IEnumerable<T> ConcatItem<T>(this IEnumerable<T> target, T item)
{
if (null == target) throw new ArgumentException(nameof(target));
foreach (T t in target) yield return t;
yield return item;
}
/// <summary>
/// Inserts the specified element at the start of the IEnumerable.
/// </summary>
/// <typeparam name="T">The type of elements the IEnumerable contans.</typeparam>
/// <param name="target">The IEnummerable.</param>
/// <param name="item">The item to be concatenated.</param>
/// <returns>An IEnumerable, enumerating first the target elements, and then the new element.</returns>
public static IEnumerable<T> ConcatTo<T>(this IEnumerable<T> target, T item)
{
if (null == target) throw new ArgumentException(nameof(target));
yield return item;
foreach (T t in target) yield return t;
}
}
或者,您可以使用隐式创建的数组(使用 params 关键字),以便您可以调用该方法一次添加一个或多个项目:
public static class Utility
{
/// <summary>
/// Adds the specified element at the end of the IEnummerable.
/// </summary>
/// <typeparam name="T">The type of elements the IEnumerable contans.</typeparam>
/// <param name="target">The target.</param>
/// <param name="items">The items to be concatenated.</param>
/// <returns>An IEnumerable, enumerating first the items in the existing enumerable</returns>
public static IEnumerable<T> ConcatItems<T>(this IEnumerable<T> target, params T[] items) =>
(target ?? throw new ArgumentException(nameof(target))).Concat(items);
/// <summary>
/// Inserts the specified element at the start of the IEnumerable.
/// </summary>
/// <typeparam name="T">The type of elements the IEnumerable contans.</typeparam>
/// <param name="target">The IEnummerable.</param>
/// <param name="items">The items to be concatenated.</param>
/// <returns>An IEnumerable, enumerating first the target elements, and then the new elements.</returns>
public static IEnumerable<T> ConcatTo<T>(this IEnumerable<T> target, params T[] items) =>
items.Concat(target ?? throw new ArgumentException(nameof(target)));
没有一种单一的方法可以做到这一点。最接近的是Enumerable.Concat
方法,但它试图将一个IEnumerable<T>
与另一个IEnumerable<T>
组合在一起。您可以使用以下方法使其与单个元素配合使用。
image.Layers.Concat(new [] { image.ParentLayer });
或者只需添加一个新的扩展方法
public static IEnumerable<T> ConcatSingle<T>(this IEnumerable<T> enumerable, T value) {
return enumerable.Concat(new [] { value });
}
I once made a nice little function for this:
public static class CoreUtil
{
public static IEnumerable<T> AsEnumerable<T>(params T[] items)
{
return items;
}
}
image.Layers.Append(CoreUtil.AsEnumerable(image.ParentLayer, image.AnotherLayer))
AsEnumerable
已成为内置扩展方法,因此可能需要使用不同的名称。此外,AsX
暗示它是一个扩展方法(方法不应该是动词吗?),所以我认为一开始就不是一个好名字。我建议使用 Enumerate
。 - ErikEToEnumerable
。Enumerate
也不错。 - Gert ArnoldToEnumerable
建议使用扩展方法。那么 CreateEnumerable
怎么样? :) - ErikEimage.Layers.Concat(new[] { image.ParentLayer });
如果你喜欢.With的语法,可以把它写成扩展方法。IEnumerable不会注意到另一个扩展方法。
我使用以下扩展方法来避免创建无用的Array
:
public static IEnumerable<T> ConcatSingle<T>(this IEnumerable<T> enumerable, T value) {
return enumerable.Concat(value.Yield());
}
public static IEnumerable<T> Yield<T>(this T item) {
yield return item;
}
.Concat(new[] { ... })
有一个缺点:如果要添加的项也实现了IEnumerable<T>
,那么Append
方法将默认添加IEnumerable<T>
,而你可能只是想添加T
。 - extremeandyimage.Layers = image.Layers.Append(image.ParentLayer)
(可能还需要执行image.Layers = image.Layers.Append(image.ParentLayer).ToArray()
或类似操作)才能获得预期的效果。 - ruffin