如果(对象是HashSet<>),为什么我不能写,但如果我写(object.GetType()== typeof(HashSet<>))它也没关系

时间:2014-04-29 18:04:08

标签: c# generics

标题说明了一切,这里有一些格式:

为什么我不能写

public bool IsHashSet(object obj)
{
    return obj is HashSet<>;
}

但这没关系:

public bool IsHashSet(object obj)
{
    return obj.GetType() == typeof(HashSet<>);
}

所有仿制药也是如此,并且不限于HashSet

2 个答案:

答案 0 :(得分:34)

你的功能

public bool IsHashSet(object obj)
{
  return obj.GetType() == typeof(HashSet<>);
}

将为false的每个可能值返回objnull除外,在这种情况下,它会抛出NullReferenceException。它将检查obj是否为哈希集。 typeof(HashSet<int>)typeof(HashSet<>)是两种不同的类型。

出于同样的原因,obj is HashSet<>被拒绝了。这完全没用。这两个函数之间的唯一区别是,一个在编译器知道的方式中是无用的,另一个在编译器不知道的方式中是无用的。

您可以使用type.IsGenericTypetype.GetGenericTypeDefinition(),然后将后者的结果与typeof(HashSet<>)进行比较。但是,您应该问自己这是否有用:如果obj is HashSet<int>来自trueobj也会评估为HashSet<int>。使用obj.GetType()需要您自己检查类层次结构。

您可以编写一个可重用的辅助函数来检查其他泛型类型:

public static bool IsInstanceOfGenericType(object obj, Type genericType) {
  if (obj == null)
    return false;

  var type = obj.GetType();
  while (type != null) {
    if (type.IsGenericType && type.GetGenericTypeDefinition() == genericType)
      return true;

    type = type.BaseType;
  }
  return false;
}

您可以将其称为IsInstanceOfGenericType(someObject, typeof(HashSet<>))

回复您的意见:

  

我对HashSet<>的理解意味着任何通用的HashSet,所以也许这会有效typeof(HashSet<>).IsAssignableFrom(HashSet<int>)

不会。您可能正在考虑使用Java,据我所知它确实有类似的东西,但C#却没有。 HashSet<int>HashSet<>是相关类型,但它们的关系与继承无关。

  

如果不是HashSet<>

的含义

在获得任何特定类型参数之前,它是HashSet<T>类型。它可用于构造实际类型,例如在var t = typeof(int);之后,typeof(HashSet<>).MakeGenericType(t)可用于获取typeof(HashSet<int>)。如果在编译时不知道t,那么它会很有用。但是在这种动态类型构造之外,它没有意义。

  

为什么写在typeof()但不在is HashSet<>中有效?

它对is HashSet<>无效,因为它永远不会有意义。构造任何类型为HashSet<>的对象是不可能的。

答案 1 :(得分:6)

两者都没有实际效果,只是第一个会在编译时失败。你可能想要的是这样的:

public bool IsHashSet(object obj)
{
    if (obj != null) 
    {
        var t = obj.GetType();
        if (t.IsGenericType) {
            return t.GetGenericTypeDefinition() == typeof(HashSet<>);
        }
    }
    return false;
}