如何确定一个类型是否为HashSet类型,并如何将其转换?

5

我在GitHub上有人要求能够比较我的项目中的HashSets:https://github.com/GregFinzer/Compare-Net-Objects/。我需要确定一个类型是否为哈希集合,然后获取枚举器,但我不确定应该将其转换为什么类型。这是我现在对于IList的代码:

private bool IsIList(Type type)
{
    return (typeof(IList).IsAssignableFrom(type));
}


private void CompareIList(object object1, object object2, string breadCrumb)
{
    IList ilist1 = object1 as IList;
    IList ilist2 = object2 as IList;

    if (ilist1 == null) //This should never happen, null check happens one level up
        throw new ArgumentNullException("object1");

    if (ilist2 == null) //This should never happen, null check happens one level up
        throw new ArgumentNullException("object2");

    try
    {
        _parents.Add(object1);
        _parents.Add(object2);

        //Objects must be the same length
        if (ilist1.Count != ilist2.Count)
        {
            Differences.Add(string.Format("object1{0}.Count != object2{0}.Count ({1},{2})", breadCrumb,
                                              ilist1.Count, ilist2.Count));

            if (Differences.Count >= MaxDifferences)
                return;
        }

        IEnumerator enumerator1 = ilist1.GetEnumerator();
        IEnumerator enumerator2 = ilist2.GetEnumerator();
        int count = 0;

        while (enumerator1.MoveNext() && enumerator2.MoveNext())
        {
            string currentBreadCrumb = AddBreadCrumb(breadCrumb, string.Empty, string.Empty, count);

            Compare(enumerator1.Current, enumerator2.Current, currentBreadCrumb);

            if (Differences.Count >= MaxDifferences)
                return;

            count++;
        }
    }
    finally
    {
        _parents.Remove(object1);
        _parents.Remove(object2);
    }
}

为什么不直接使用 ICollection - SLaks
这不起作用:public bool IsHashSet(Type type) { return (typeof(ICollection).IsAssignableFrom(type)); }[Test] public void IsHashSet() { HashSet<int> hashSet = new HashSet<int>(); Type type = hashSet.GetType(); Assert.IsTrue(_compare.IsHashSet(type)); } - Greg Finzer
4个回答

4

我认为直接使用 ISet<T>ICollection<T>IEnumerable<T> 泛型接口就足够了,而不需要使用 HashSet<T>。你可以使用以下方法来检测这些类型:

// ...
    Type t = typeof(HashSet<int>);
    bool test1 = GenericClassifier.IsICollection(t); // true
    bool test2 = GenericClassifier.IsIEnumerable(t); // true
    bool test3 = GenericClassifier.IsISet(t); // true
}
//
public static class GenericClassifier {
    public static bool IsICollection(Type type) {
        return Array.Exists(type.GetInterfaces(), IsGenericCollectionType);
    }
    public static bool IsIEnumerable(Type type) {
        return Array.Exists(type.GetInterfaces(), IsGenericEnumerableType);
    }
    public static bool IsISet(Type type) {
        return Array.Exists(type.GetInterfaces(), IsGenericSetType);
    }
    static bool IsGenericCollectionType(Type type) {
        return type.IsGenericType && (typeof(ICollection<>) == type.GetGenericTypeDefinition());
    }
    static bool IsGenericEnumerableType(Type type) {
        return type.IsGenericType && (typeof(IEnumerable<>) == type.GetGenericTypeDefinition());
    }
    static bool IsGenericSetType(Type type) {
        return type.IsGenericType && (typeof(ISet<>) == type.GetGenericTypeDefinition());
    }
}

这也将捕获“字典”类型。 - GaspardP
@GaspardP 是的,这里没有任何问题,因为字典既是IEnumerable又是ICollection。此外,由于任务的特定性,不需要确切地使用HashSet。因此,我不认为有任何降低评分的理由。 - DmitryG
我遇到的问题是关于问题标题的,"如何确定类型是否为HashSet类型以及如何进行强制转换?" 暗示着被接受的答案将提供一个测试来判断类型是否为HashMap。在这种情况下,该测试将无法区分HashMapDictionary - GaspardP
@GaspardP 与 HashSet<T> 类型完全配合可以缩小结果解决方案的范围,但从字面上讲,你是正确的。因此,我稍微更新了我的答案。谢谢。 - DmitryG

1

被接受的答案没有区分Dictionary类型和可能是ICollectionIEnumerable的其他子类。这个更好:

Type t1 = typeof(HashSet<int>);
bool test1 = t1.IsGenericType && 
    t1.GetGenericTypeDefinition() == typeof(HashSet<>); // true

Type t2 = typeof(Dictionary<int, string>);
bool test2 = t2.IsGenericType && 
    t2.GetGenericTypeDefinition() == typeof(HashSet<>); // false

Type t3 = typeof(int);
bool test3 = t3.IsGenericType && 
    t3.GetGenericTypeDefinition() == typeof(HashSet<>); // false

1
你需要循环遍历 GetInterfaces() 并检查它是否实现了一个接口,其中 IsGenericType 为 true,且 GetGenericTypeDefinition() == typeof(ISet<>)

-1

我需要使用反射来找出差异。 - Greg Finzer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接