Ответ 1
Ваша функция
public bool IsHashSet(object obj)
{
return obj.GetType() == typeof(HashSet<>);
}
вернет false
для каждого возможного значения obj
, кроме null
, и в этом случае он выкинет NullReferenceException
. Он не проверяет, является ли obj
хэш-набор. typeof(HashSet<int>)
и typeof(HashSet<>)
- два разных типа.
По той же причине, что obj is HashSet<>
отклоняется. Это совершенно бесполезно. Единственная разница между этими двумя функциями заключается в том, что один бесполезен в том, как компилятор знает об этом, а другой бесполезен в способе, о котором компилятор не знает.
Вы можете использовать type.IsGenericType
и type.GetGenericTypeDefinition()
, а затем сравнить результат последнего с typeof(HashSet<>)
. Однако вы должны спросить себя, полезно ли это: obj is HashSet<int>
также оценивает значение true
, если obj
выводится из 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, которая, как я понимаю, имеет что-то подобное, но С# этого не делает. HashSet<int>
и HashSet<>
являются родственными типами, но их отношение не связано с наследованием.
если нет значения
HashSet<>
Это тип HashSet<T>
, прежде чем он получит какой-либо конкретный аргумент типа. Его можно использовать для построения реальных типов, например, после var t = typeof(int);
, typeof(HashSet<>).MakeGenericType(t)
можно использовать для получения typeof(HashSet<int>)
. Это может быть полезно, если t
не известно во время компиляции. Но вне такой конструкции динамического типа это не имеет смысла.
и почему это допустимо для записи в
typeof()
, но не вis HashSet<>
?
Недействительно с is HashSet<>
, потому что это никогда не будет значимым. Невозможно построить объект, тип которого HashSet<>
.