Skip to main content
 首页 » 编程设计

c#之如何检查通用类型 T 是否为 IEnumerableT'>,其中 T' 未知

2024年06月20日53Terrylee

我写了一个这样的扩展方法:

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在一起。