如何在C#中以高效的方式检查类是叶类(无后代类)?

时间:2015-01-28 02:57:03

标签: c# inheritance

我正在使用以下代码,发现效率非常低,因为我经常调用该函数。

public static bool IsLeafType(this Type type)
{
    try
    {
        return AppDomain.CurrentDomain.GetAssemblies()
                                      .SelectMany(p => p.GetTypes())
                                      .Any(p => p.IsSubclassOf(type));
    }
    catch
    {
        return true;
    }
}

当然,密封类是叶类,但也许非密封类也没有子类。

1 个答案:

答案 0 :(得分:0)

如果我的计算是正确的,这将是一个懒惰的评估哈希集,它包含第一次调用它时的所有叶类。后续调用是在hashset中快速查找。

void Main()
{
    var a = typeof(TextWriter).IsLeafType(); //false
    var b = typeof(StreamWriter).IsLeafType(); //true
}

static class Ex
{
    private static Lazy<ISet<Type>> typeSetLazy =
        new Lazy<ISet<Type>>(() => {
            var types = AppDomain
                        .CurrentDomain
                        .GetAssemblies()
                        .SelectMany(a => a.GetTypes()
                                          .Where(t=>t.IsClass));
            var typesAndBaseTypes = types
                                    .Select(t => new { Type = t, t.BaseType })
                                    .ToList();
            var typesWithSubclasses = typesAndBaseTypes
                                        .Join(
                                            typesAndBaseTypes,
                                            t => t.Type,
                                            t => t.BaseType,
                                            (t1, t2) => t2.BaseType);
            var typesHs = new HashSet<Type>(types);
            typesHs.ExceptWith(typesWithSubclasses);
            return typesHs;
        });
    public static bool IsLeafType(this Type type)
    {
        return typeSetLazy.Value.Contains(type);
    }
}

...当然,缓存仅在创建时有效。