我写了一个这样的扩展方法:
public static String Join<T>(this IEnumerable<T> enumerable)
{
if (typeof(T) is IEnumerable<T'> where T' is unknown at compile time)
{
return String.Join(",", enumerable.Select(e => e.Join()));
}
return String.Join(",", enumerable.Select(e => e.ToString()));
}
问题是我不知道如何在 if 语句中编写代码以使其工作。 有什么建议吗?谢谢!
请您参考如下方法:
因为您只调用了 .ToString()
你实际上并不真正关心 T 是什么,只要它实现了 IEnumerable
或不。以下是如何在没有反射的情况下仅使用 IEnumerable
来做到这一点而不是 IEnumerable<T>
, 我为 String.Join
做我自己的逻辑因为它使编写递归逻辑代码变得更容易。
internal static class ExtensionMethods
{
public static String Join<T>(this IEnumerable<T> enumerable)
{
StringBuilder sb = new StringBuilder();
JoinInternal(enumerable, sb, true);
return sb.ToString();
}
private static bool JoinInternal(IEnumerable enumerable, StringBuilder sb, bool first)
{
foreach (var item in enumerable)
{
var castItem = item as IEnumerable;
if (castItem != null)
{
first = JoinInternal(castItem, sb, first);
}
else
{
if (!first)
{
sb.Append(",");
}
else
{
first = false;
}
sb.Append(item);
}
}
return first;
}
}
Here is a test program我写的显示一切正常(它测试类、结构和 IEnumerables 3 层深)。
编辑:根据您在这里的评论,这是另一个版本,它可以展平嵌套的 IEnumerables,您可以在完成后对每个元素做任何您想做的事情。
internal static class ExtensionMethods
{
public static IEnumerable<T> SelectManyRecusive<T>(this IEnumerable enumerable)
{
foreach (var item in enumerable)
{
var castEnumerable = item as IEnumerable;
if (castEnumerable != null
&& ((typeof(T) != typeof(string)) || !(castEnumerable is string))) //Don't split string to char if string is our target
{
foreach (var inner in SelectManyRecusive<T>(castEnumerable))
{
yield return inner;
}
}
else
{
if (item is T)
{
yield return (T)item;
}
}
}
}
}
我还遇到了一个错误,我认为它可能会影响我回答的第一部分,string
技术上是 IEnumerable<char>
所以IEnumerable<string>
也可以被视为 IEnumerable<IEnumerable<char>>
它可能会放太多 ,
in。第二个版本对此进行了检查。
Test program显示如何使用此方法和 String.Join
在一起。