IS和AS和IsAssignableFrom有什么区别?在检查对象类型和接口时有什么不同?

7

我是一名初学者,对C#不太熟悉,希望你能帮助我。

情境描述:

public bool ObjectImplementsSpecificInterface (object obj)
{
    // 1.
    if (obj is IExampleInterface) 
    {
        return true;
    }

    // 2.
    var tmp = obj as IExampleInterface;
    if (tmp != null) 
    {
        return true;
    }

    // 3.
    if (typeof(IExampleInterface).IsAssignableFrom (obj.GetType ())) 
    {
        return true;
    }
}

目标:确定对象o是否实现了给定接口定义IExampleInterface

问题:

  • 哪种实现方式是最佳实践?
  • 不考虑第一个问题,哪一种是技术上最正确的?
  • 这些运算符的具体区别是什么?MSDNAA在它们上面没有真正详细的说明。
  • 哪个调用需要最长/最短时间?

在需要进一步使用值时,请使用is结构(变体1)或as(变体2)。 - General-Doomer
1
我无法想象这里之前没有涉及过这个问题。 - crashmstr
我也这么认为,但我只能找到关于特定运算符的答案,而没有相互比较的答案。如果你找到一个回答我的问题的帖子,请随意链接它! :) - user4030492
4:typeof(IExampleInterface).IsInstanceOfType(obj)。在调用 obj.GetType() 之前,应该检查 obj 是否为 null。 - user4003407
5个回答

6
“Is”操作符允许您检查特定实例是否属于特定类型或继承该类型,而IsAssignableFrom允许您检查类型是否可转换为另一种类型。
因此,如果您需要评估某个对象是否属于特定类型,则使用is:
Random r = new Random();
if (r is Random)
{
    reutrn true;
}

但是如果你只有像这样的方法类型:
public bool CheckIfTypeIsRandom(Type typeKnownAtRuntime)
{
     if (typeof(Random).IsAssignableFrom(typeKnownAtRuntime) 
     {
         return true;
     }
     return false;
}

那么您必须使用IsAssignableFrom。


5
所有三种方法都会提供相同的结果,并且需要大致相同的时间,但只有第一种方法是专门为您的情况设计的。
当您从一个对象开始,而您所需知道的仅是其类是否实现了给定接口时,第一种方法(即is运算符)是最合适的。
第二种方法适用于需要找出对象是否实现了接口,并在将其转换为接口后使用该对象的情况。如果您计划在null检查后丢弃类型转换的结果,则首先执行类型转换没有意义。
第三种方法主要用于反射,当您拥有System.Type对象而不是对象本身时使用。

第三种方法主要用于反射,当你拥有一个 System.Type 对象而不是对象本身时使用。即使对于泛型,它也有一些用途... - xanatos

3
下面是翻译的结果:

以下是从下面帖子中收集到的信息和可能正确的答案:

运算符is:

  • 应该用来确定对象是否实现了一个接口或者是特定类型,所以这就是我的问题的答案: 哪一个是最佳实践?

运算符as:

  • is花费的时间更长。
  • 通常用于将对象存储到将表示正确类型的var中。
  • 用于进一步处理对象,即调用函数或检查接口的类型。

运算符isAssignableFrom:

  • 检查对象是否可以转换为另一种类型。
  • 如果对象的类型在运行时是未知的,则应使用它。

1
  1. var impInterface = obj 是 ISampleInterface 接口的实现;
  2. "技术上"是什么意思?它们都可以工作。如果你只想知道它是否实现了接口,那就用 is。如果你想要一个新的变量强制转换成接口类型,那就使用 as
  3. is 用于确定对象是否派生自某个类型,并返回一个布尔值。 as 试图将对象强制转换为该类型,并返回已转换为该类型的新变量,如果无法转换则返回 null。(但你从你的问题中已经知道这一点了)。
  4. 即使转换成功,as 的耗时可能会更长。

这是上述评论的参考链接:https://msdn.microsoft.com/zh-cn/library/cscsdfbt.aspx 我也正要发表同样的观点。 - Ron Beyer
我所说的“技术上”是指从最接近C#的角度来看。因此,基本上在查看C#的工作方式时,哪种方法是正确的。 - user4030492
我对“c-Sharp-ish”是什么意思也感到困惑。显然它们都是C#。哪一个是“正确的选择”取决于你要做什么,是确定变量是否引用了从某个指定类型派生的对象,还是将其强制转换为该类型。就是这样简单。 - Charles Bretana

0

1) 如果你只是想检查一个对象是否是某种类型或实现了某个接口,可以使用 is

2) 如果你想检查类型或接口并对对象进行一些操作,请使用 as。所以,不要这样写:

if (obj is A) {
    A casted = (A) obj;
    casted.MethodOfA ();
}

你应该这样做

A casted = obj as A
if (casted != null) {
    casted.MethodOfA ();
}

3)仅在 1)不可用时使用此方法,例如您具有类型为 Type 而不是 T 的对象。


糟糕,我的错。不好意思,反射并没有参与其中。 - Residuum

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