简体   繁体   English

为什么我不能写if(object是HashSet <>)但是如果我写的话就没关系(object.GetType()== typeof(HashSet <>))

[英]Why can't I write if (object is HashSet<>) but it's okay if I write (object.GetType() == typeof(HashSet<>))

The title says it all, here's the same with some formatting: 标题说明了一切,这里有一些格式:

Why can't I write 为什么我不能写

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

but this is okay: 但这没关系:

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

(The same goes for all generics and isn't limited to HashSet ) 所有泛型都是如此,并且不限于HashSet

Your function 你的功能

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

will return false for every possible value of obj , except null , in which case it will throw a NullReferenceException . 将为obj每个可能值返回false ,除了null ,在这种情况下它将抛出NullReferenceException It will not check if obj is a hash set. 不会检查obj是否是哈希集。 typeof(HashSet<int>) and typeof(HashSet<>) are two different types. typeof(HashSet<int>)typeof(HashSet<>)是两种不同的类型。

It is for that same reason that obj is HashSet<> is rejected. 出于同样的原因, obj is HashSet<>被拒绝。 It's completely useless. 这完全没用。 The only difference between the two functions is that one is useless in a way the compiler knows about, and the other is useless in a way the compiler doesn't know about. 这两个函数之间的唯一区别是,一个在编译器知道的方式中是无用的,另一个在编译器不知道的方式中是无用的。

You can use type.IsGenericType and type.GetGenericTypeDefinition() , then compare the result of the latter to typeof(HashSet<>) . 您可以使用type.IsGenericTypetype.GetGenericTypeDefinition() ,然后将后者的结果与typeof(HashSet<>) However, you should ask yourself if that is useful: obj is HashSet<int> would also evaluate to true if obj is derived from HashSet<int> . 但是,您应该问自己这是否有用:如果obj是从HashSet<int>派生的,则obj is HashSet<int>也会计算为true Working with obj.GetType() would require you to check the class hierarchy yourself. 使用obj.GetType()需要您自己检查类层次结构。

You can write a reusable helper function to check this for other generic types too: 您可以编写一个可重用的辅助函数来检查其他泛型类型:

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;
}

You can call this as IsInstanceOfGenericType(someObject, typeof(HashSet<>)) . 您可以将其称为IsInstanceOfGenericType(someObject, typeof(HashSet<>))

To respond to your comments: 回应你的意见:

In my understanding of HashSet<> would mean HashSet of any generic, so maybe this would work typeof(HashSet<>).IsAssignableFrom(HashSet<int>) 在我对HashSet<>理解中,将意味着任何泛型的HashSet ,所以也许这将工作typeof(HashSet<>).IsAssignableFrom(HashSet<int>)

It would not. 它不会。 It's possible you're thinking of Java, which as I understand it does have something like that, but C# does not. 您可能正在考虑使用Java,据我所知它确实有类似的东西,但C#却没有。 HashSet<int> and HashSet<> are related types, but their relation is not one related to inheritance. HashSet<int>HashSet<>是相关类型,但它们的关系不是与继承相关的关系。

if not whats the meaning of HashSet<> 如果不是HashSet<>的含义

It is the HashSet<T> type before it has got any specific type argument. 在获得任何特定类型参数之前,它是HashSet<T>类型。 It can be used to construct the real types, for example after var t = typeof(int); 它可用于构造实数类型,例如在var t = typeof(int); , typeof(HashSet<>).MakeGenericType(t) can be used to get typeof(HashSet<int>) . typeof(HashSet<>).MakeGenericType(t)可用于获取typeof(HashSet<int>) It can be useful if t is not known at compile-time. 如果在编译时不知道t那将非常有用。 But outside of such dynamic type construction, it is not meaningful. 但是在这种动态类型构造之外,它没有意义。

and why is it valid to write in a typeof() but not in is HashSet<> ? 为什么在typeof()写入是有效的但不是在is HashSet<>

It's not valid with is HashSet<> because it would never be meaningful. 它与is HashSet<>无效,因为它永远不会有意义。 It is impossible to construct any object whose type is HashSet<> . 构造任何类型为HashSet<>对象是不可能的。

Neither actually works, it's just that the first one will fail at compile time. 两者都没有实际工作,只是第一个在编译时会失败。 What you probably want is something like this: 你可能想要的是这样的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM