IT教程 ·

多用as罕用强迫范例转换

在 C# 中存在一个名叫静态范例搜检的机制,这个机制可以让编译器协助我们把范例不服的用法找出来,从而使得应用程序在运转时期加少一些范例搜检的操纵。然则有时刻我们照样须要举行运转期范例搜检,比方我们在设想框架时将要领的参数范例定义为 object ,那末这时刻我们就有很大的大概须要将 object 范例的参数先转换为其他范例。我们举行转换时会有两种要领可以运用:一种是强迫范例转换,这类要领可以绕过编译器的范例搜检,另一种是先经由过程 is 推断操纵是不是合理,是不是可以转换,然后再运用 as 运算符举行转换,或许运用强迫范例转换。下面我们就来解说一下为何多运用 as 少运用强迫范例转换。

零、as and is

运用 as 举行范例转换会比强迫范例转换越发平安,而且运转时效力更高。然则这里有一点须要注重的是 as 和 is 运算符不会斟酌用户所定义的范例转换,只要当运转期的范例与要转换到的范例符合时才顺利举行。一般来说 as 范例转换很少会涌现为了范例转换而建立新的对象,只要在 as 运算符把装箱值范例转换未装箱且可以为 null 的范例时才会建立新对象。
is 运算符遵照多态准绳,也就是说比方 变量 Husky(哈士奇)是 Dog 范例,而且 Dog 范例继续自 Animal 范例,那末 代码段 husky is Animal 返回值就是 True 。因而我们可以应用这一特征来推断某个对象是不是是某个细致范例。固然我们也可用经由过程 GetType 要领来查询对象的运转期范例,如许可以使开发人员写出比 as 和 is 越发细致越发细致的范例,这重要归功于它所返回的对象范例可以和某种特定范例举行对照。

一、为何不必强迫范例转换

我们先来看一段代码:

try
{
    object obj = Factory.GetObject();
    Animal animal;
    animal = (Animal) obj;
    if (animal !=null)
    {
        // more code
    }
    // more code
}
catch (InvalidCastExcept ex)
{
    // more code
}

在上述代码中我们运用了强迫范例转换将 object 范例的变量转换为 Animal 范例,我置信部份开发人员在现实开发中都邑这么写,这么些也不为过,然则这个中存在一个问题,开发人员须要处置惩罚两个问题。起首程序假如没法将变量 obj 转换为 Animal 范例将抛出 InvalidCastException 非常,因而我们必需捕捉,其次在强迫范例转换时碰到 null 的时刻并不会抛出非常,因而我们还要推断变量 animal 是不是为 null 。既然强迫范例转换有这个问题,那我们该怎样处理呢?这时刻我们就可以用到 as 和 is 运算符了,一样我们先看一下代码:

try
{
    object obj = Factory.GetObject();
    if (obj is Animal)
    {
        Animal animal =  obj as Animal;
        // more code
    }
    else
    {
        // more code
    }
}

应用这类要领我们起首推断 obj 是不是可以转换为 Animal 范例,假如可以就应用 as 运算符来转换,反之实行其他代码。既不须要捕捉毛病,也不须要强迫转换,减少了代码量同时也减少了代码失足的机率。
as 运算符和强迫范例转之间有一个很大的区分,那就是怎样看待用户自定义的转换逻辑。 as 和 is 运算符除了必需举行的装箱和拆箱外,它不会实行其他任何操纵,也就是说 as 和 is 只会推断带转换对象在运转期是什么范例,并依据效果举行响应的处置惩罚。那末假如带转换对象既不属于目的范例也不属于目的范例所派生出来的范例的话, as 操纵就宣布失利。强迫范例转换则不然,它有大概运用一些范例的转换逻辑举行范例转换,而且不仅仅是用户自定义的转换逻辑,还包含了内置范例之间的转换。然则要注重的是强迫范例转换可以会形成信息丧失,比方从 long 强迫转换为 short 。
在某些情况下应用强迫范例转换从代码上来看好像可以转换胜利,但现实上却转换不胜利。这时刻为何呢?虽然强迫范例转换会把用户自定义的转换逻辑斟酌进去,然则它只针对对象的编译期范例,编译期范例并非是基范例。比方带转换范例在编译期是 object 范例,因而编译器会将它看做 object ,这时刻假如举行强迫范例转换的话就会报错。
前面说了那末多运用 as 的优点,那末在这一小节里我们就来说说在什么时刻不能运用 as 和 is 。一样,先来看一小段代码:

object obj =Factory.GetValue();
int num = obj as int;

上面的这段代码运转起来后将会报错,为何呢?这是由于当 obj 不是 int 范例时返回的值是 null ,然则 int 范例没法接收 null 值。因而当指定范例不可接收 null 值时 as 没法举行范例转换。

二、一个问题

下面我们再思索一个问题,我们都晓得 foreach 所针对的序列黑白泛型序列它会在迭代过程当中自动转换,那末 foreach 的范例转换运用的是 as 呢照样强迫范例转换呢?
foreach 运用的时强迫范例转换,会把对象从 object 范例转换成循环体所须要的范例,之所以运用强迫范例转换是由于 foreach 须要同时应对值范例和援用范例。

三、总结

在开发中我们应当只管防止运用强迫范例转换,强迫范例转换在某些情况下大概会涌现开发人员预感以外的效果,运用 as 和 is 运算符可以确保对象确切可以举行范例转换时才给出答案,如许可以保证程序的正确性。

参与评论