C# 使用类型时考虑所有继承类

C# 使用类型时考虑所有继承类,c#,inheritance,C#,Inheritance,我有几个类(其中一个叫做Pet)扩展了类Animal。如果我有一个泛型方法,我可以使用typeof与基类进行比较吗 if (typeof(T) == typeof(Animal)) { return ((Animal)pet).Color; } 目前在我的代码中发生的是,这个子句被完全跳过了。这在这个特定的例子中是不需要的,因为Pet继承自Animal,而不是使用typeof(t)==typeof(Animal),请执行以下操作: var animal = pet as Animal;

我有几个类(其中一个叫做
Pet
)扩展了类
Animal
。如果我有一个泛型方法,我可以使用
typeof
与基类进行比较吗

if (typeof(T) == typeof(Animal))
{
    return ((Animal)pet).Color;
}

目前在我的代码中发生的是,这个子句被完全跳过了。这在这个特定的例子中是不需要的,因为
Pet
继承自
Animal
,而不是使用
typeof(t)==typeof(Animal)
,请执行以下操作:

var animal = pet as Animal;
if(animal != null)
  return animal.Color;
这为您节省了额外的类型检查

关于
as
is

as
只能用于引用类型。如果您尝试使用
as
进行强制转换,但失败。。。它将返回
null
。如果您只想检查某个值是否属于特定类型,请使用
is
。它返回一个
布尔值

其中
关键字

但是,让我们也看看你能用泛型做些什么

public void Foo<T>(T pet)
  where T : Animal
{
}

更干净更快

不要使用
typeof(T)==typeof(Animal)
,而是:

var animal = pet as Animal;
if(animal != null)
  return animal.Color;
这为您节省了额外的类型检查

关于
as
is

as
只能用于引用类型。如果您尝试使用
as
进行强制转换,但失败。。。它将返回
null
。如果您只想检查某个值是否属于特定类型,请使用
is
。它返回一个
布尔值

其中
关键字

但是,让我们也看看你能用泛型做些什么

public void Foo<T>(T pet)
  where T : Animal
{
}

更干净更快

在大多数情况下,我个人会选择C#
作为
操作员(参见Andrew的回答),但根据需要,您也可以使用:

if (typeof(Animal).IsAssignableFrom(typeof(T)))
{
    return ((Animal)pet).Color;
}
另一方面,我通常更喜欢
Type.IsAssignableFrom
而不是
Type.IsSubclassOf
,因为
IsAssignableFrom
也适用于接口

哦,你也可以用:


在大多数情况下,我个人会选择C#
作为
操作员(参见Andrew的回答),但根据需要,您也可以使用:

if (typeof(Animal).IsAssignableFrom(typeof(T)))
{
    return ((Animal)pet).Color;
}
另一方面,我通常更喜欢
Type.IsAssignableFrom
而不是
Type.IsSubclassOf
,因为
IsAssignableFrom
也适用于接口

哦,你也可以用:


你为什么不试着运行它来找出答案呢。但请注意,即使你可以,你也不应该。需要明确检查对象的类型通常是代码设计不良的标志。如果(宠物是动物)使用
if(宠物是动物)
Animal a=pet作为动物;如果(a!=null)返回a.颜色@Servy我问这个问题是因为我当前的代码不起作用。你想使用通用约束吗?如果你需要做这样的事情,几乎总是因为糟糕的设计。您的类/函数将变得难以维护和扩展。尝试使用一些多态性。为什么不试着运行它来找出答案呢。但请注意,即使你可以,你也不应该。需要明确检查对象的类型通常是代码设计不良的标志。如果(宠物是动物)使用
if(宠物是动物)
Animal a=pet作为动物;如果(a!=null)返回a.颜色@Servy我问这个问题是因为我当前的代码不起作用。你想使用通用约束吗?如果你需要做这样的事情,几乎总是因为糟糕的设计。您的类/函数将变得难以维护和扩展。尝试使用一些多态性,“关于as和is的注释”是不正确的,因为太多的通用性。它不会返回您试图强制转换的对象的默认值。事实上它会,但是默认值总是
null
。对于非引用类型的类型,不能使用
as
运算符。所有引用类型的默认值均为
null
。想象一下,在这种笨拙的设计中,
除了作为BOOL的BOOL之外的任何东西都会返回
false
。试着想象这样一个世界,并记住,
bool
正好有两个值。这些值中的一半将是除
true
:)@eduardumitru之外的所有内容的总括。您可以将
作为
与可为空的值类型一起使用,这些值类型不是引用类型,而是事实上的值类型,如果类型转换不成功,它会指定所述类型的默认值。您提议的更改会将正确的声明更改为不正确的声明。很公平。。。我并没有考虑到这样一个事实,即引用类型是必需的,这可能不是常识。但你还是理解我的担心,对吗?我真的很抱歉对一些完全不正确的事情如此激烈,但正如您所说:“您可以将
用作
和可空值类型”。这是BCL的一个通用结构加上它的特殊性。我认为向人们提到这一点很重要:它是引用类型,然后是
可空的
和没有其他值类型,而不是简单地说
default(T)
通常是
操作的结果。所以我同意。答案是正确的。也许这不是教育学上的“关于as和is的注释”是不正确的,因为太笼统了。它不会返回您试图强制转换的对象的默认值。事实上它会,但是默认值总是
null
。对于非引用类型的类型,不能使用
as
运算符。所有引用类型的默认值均为
null
。想象一下,在这种笨拙的设计中,
除了作为BOOL的BOOL之外的任何东西都会返回
false
。试着想象这样一个世界,并记住,
bool
正好有两个值。这些值的一半将是除
true
:)@E之外的所有值