1.1.1 摘要

C#是一门强类型语言,一般情况下,我们最好避免将一个类型强制转换为其他类型,但有些时候难免要进行类型转换。

先想想究竟哪些操作可以进行类型转换(先不考虑.NET提供的Parse),一般我们都有以下选择:

  • 使用as操作符转换,
  • 使用传统C风格的强制转型
  • 使用is来做一个转换测试,然后再使用as操作符或者强制转

1.1.2 正文

正确的选择应该是尽可能地使用as操作符,因为它比强制转型要安全,而且在运行时层面也有比较好的效率(注意的是as和is操作符都不执行任何用户自定义的转换,只有当运行时类型与目标转换类型匹配时,它们才会转换成功)。

现在我们通过一个简单的例子说明as和强制转换之间的区别,首先我们定义一间获取不同类型对象的工厂,然后我们把未知类型转换为自定义类型。


object o = Factory.GetObject();
MyType t = o as MyType;
if (t ==null)
{
//转换成功
}
else
{
//转换失敗
} object o = Factory.GetObject();
try
{
MyType t = (MyType) o;
if (t !=null)
{
////转换成功
}
else
{
////转换失敗
} }
catch
{
////异常处理
}

通过上述代码我们发现as类型转换失败时值为null不抛出异常,但强制转换如果转换失败会抛出异常所以我们要添加异常处理。

现在我们对as和强制转换有了初步的了解,假设现在我们定义了一个抽象类Foo,然后Foo1继承于它,并且再定义一个基类Logger,在Foo1中定义与Logger类型隐式转换具体如下:


     Foo1 myFoo;          //// Inherits abstract class.
Logger myFoo; //// base class. publicclass Foo1 : Foo
{
private Logger _value; ///<summary>
/// 隐式自定义类型转换。
///</summary>
///<param name="foo1"></param>
///<returns></returns>
publicstaticimplicitoperator Logger(Foo1 foo1)
{
return foo1._value;
}
}

现在我们猜猜看以下的类型转换是否成功(提示:从编译和运行时类型转换角度考虑)。


object myFoo = container.Resolve<Foo>();      //获取未Foo1类型

                  try
{
Logger myFoo1 = (Logger)myFoo;
if (myFoo1 !=null)
{
Console.WriteLine("Covert successful.");
}
}
catch
{
Console.WriteLine("Covert failed.");
}

相信聪明的大家已经想出答案了,激动人心的时刻到了现在让我们公布答案:转换失败抛出异常。

图1转换失败结果

首先我们要从编译和运行时角度来分析,在编译时myFoo的类型为System.Object,这时编译器会检测是否存在自定义由Object到Logger的类型转换。如果没有找到合适转换,编译器将生成代码检测myFoo的运行时类型和Logger比较,由于myFoo的运行时类型为Foo1,而且我们自定义了由Foo1到Logger的类型转换,估计这样可以转换成功了吧!然而恰恰没有转换成功,这究竟是什么原因呢?让我们了解一下编译器对于隐式类型转换的原理吧。

图2编译和运行时自定义类型转换

通过上图我们发现用户自定义的转换操作符只作用于对象的编译时类型,而非运行时类型上,OK现在让修改一下代码让我们编译器认识自定义类型中。


            using (IUnityContainer container =new UnityContainer())
{
UnityConfigurationSection section = (UnityConfigurationSection)
ConfigurationManager.GetSection("unity"); //获取container名称为CfgClass下的配置
section.Containers["CfgClass"].Configure(container);
object tempFoo = container.Resolve<Foo>(); //获取未Foo1类型
Foo1 myFoo = tempFoo as Foo1; //使用as先把object转型为Foo1
try
{
Logger myFoo1 = (Logger)myFoo;
if (myFoo1 !=null)
{
Console.WriteLine("Covert successful.");
}
}
catch
{
Console.WriteLine("Covert failed.");
} Console.ReadKey();
}

图3转换成功结果

现在类型可以转换成功,这是因为编译器使用了我们自定义的隐式转换,由于myFoo这次的编译类型为Foo1,编译器首先查找是否存在Foo1和Logger自定义转换类型,由于我们定义了一种由Foo1到Logger的隐式类型转换所以转换成功。

通过上述我们发现了as给我们带来的好处,但是有一点我们要注意的是as只能用于引用类型不能用于值类型。那我就有个问题了在进行类型转换之前如果我们并不知道要转换的是值类型还是引用类型,那该怎么办呢?现在是is登场的时候了。

bject tempFoo = container.Resolve<Foo>();      //获取未Foo1类型
int myInt = tempFoo asint; //compile error

as不能用于值类型,这是因为值类型不能为null(注意:C#2.0中,微软提供了Nullable类型,允许用它定义包含null值,即空值的数据类型)像这种情况我们应该使用强制类型转换。


    object tempFoo = container.Resolve<Foo>();      //获取未Foo1类型
try
{
int myInt = (int)tempFoo; //转换成功
      if (myFoo1 !=null)
{
Console.WriteLine("Covert successful.");
}
}
catch
{
Console.WriteLine("Covert failed.");
}

大家可以发现和我们之前使用的强制转换类似,而且还有处理异常,现在修改一下我们代码让它更加简洁实现如下:


object tempFoo = container.Resolve<Foo>();      //获取未Foo1类型
int i =0; //值类型转换
if (tempFoo isint)
{
i = (int) tempFoo;
} object tempFoo = container.Resolve<Foo>(); //获取未Foo1类型
Logger myFoo1 =null; //引用类型转换
if (tempFoo is Logger)
{
myFoo1 = tempFoo as Logger;
}

1.1.3 总结

as和强制转换之间最大的区别就在于如何处理用户自定义的转换。操作符 as和 is 都只检查被转换对象的运行时类型,并不执行其他的操作。如果被转换对象的运行时类型既不是所转换的目标类型,也不是其派生类型,那么转型将告失败。但是强制转型则会使用转换操作符来执行转型操作,这包括任何内建的数值转换(如:long转int)。

一般情况我们应该先考虑使用as进行类型转换,然后再考虑使用is,最后才考虑使用强制转换。

as

强制转换

转换失败是否抛出异常

No

Yes

支持值类型和引用类型转换

只支持引用类型

Yes

C#中 As 和强制转换的总结的更多相关文章

  1. OC中的类型强制转换

    在Objective-C中,以数字格式组成的字符串经常需要转换为NSNumber对象后再使用.例如有一个字符串对象@"111.22",需要转为NSNumber对象,最简单的方法就是 ...

  2. java 中数据的强制转换 和计算的补码运算

    原码 反码 补码的定义与运算 1原码: 原码是将十进制或者其他进制的数转换为二进制表示(且要根据数据的类型转换) 如:130 (默认是Int类型,则是4个字节) 原码是:00000000 000000 ...

  3. php中数据类型的强制转换

    1.在PHP开发种在很多的地方要涉及到数据类型的转换,尤其是涉及到金额的数据类型,一定要转换成float类型,否则在入库的时候可能会因为数据类型的不同覆盖掉之前的金额.(字符串和float类型相加) ...

  4. How to: Use XPO Upcasting in XAF 如何:在 XAF 中使用 XPO 强制转换

    In this topic, you will learn how to use the Upcasting feature of XPO in XAF. It is useful when you ...

  5. PHP 变量类型的强制转换 & 创建空对象

    PHP 在变量定义中不需要(或不支持)明示的类型定义:变量类型是根据使用该变量的上下文所决定的. 也就是说,如果把一个字符串值赋给变量 var,var 就成了一个字符串.如果又把一个整型值赋给 var ...

  6. PHP强制转换类型

    PHP强制转换类型   获取数据类型 : 1.如果想查看某个表达式的值和类型,用var_dump(). 2.如果只是想得到一个易读懂的类型的表达方式用于调试,用 gettype().3.要查看某个类型 ...

  7. C++指针类型间强制转换

    深入理解指针类型间的转换 C++中指针的强制转换 强制类型转换(int).(int&)和(int*)的区别 内存中的地址 地址的本质就是一串0和1的机器代码,内存中的地址没有明确数据类型,但地 ...

  8. Php中的强制转换详解

    强制转换中分为两种,第一种就只临时转换,和永久转换.在临时转换中呢,首先可以通过第一中方式来显示,就是小括号的形式,临时转换成整型我们可以通过(int)都是这样的形式,或者是(integer)临时转换 ...

  9. c++中的强制转换static_cast、dynamic_cast、reinterpret_cast的不同用法儿

    c++中的强制转换static_cast.dynamic_cast.reinterpret_cast的不同用法儿   虽然const_cast是用来去除变量的const限定,但是static_cast ...

随机推荐

  1. android webview删除缓存

    [1].[代码] 删除保存于手机上的缓存. 跳至 [1] [2] [3] 01 // clear the cache before time numDays     02 private int cl ...

  2. 淘宝(阿里百川)手机客户端开发日记第六篇 Service详解(六)

    Service和Thread的关系 不少初学者都可能会有这样的疑惑,Service和Thread到底有什么关系呢?什么时候应该用Service,什么时候又应该用Thread? 答案是Service和T ...

  3. 把 表拷贝到test测试数据库

    (文章是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) bundle exec rake db:schema:load RAILS_ENV=test   注 ...

  4. HTML前端--各种小案例

    掬一捧清水,放逐在江河,融入流逝的岁月,将心洗净; 捻一缕心香,遥寄在云端,在最深的红尘里重逢,将心揉碎; 望一程山水,徘徊在月下,在相思渡口苦守寒冬,将心落寞. 案例一: 隐藏扩展域,并去掉afte ...

  5. c++0x新特性实例(比较常用的)

    //array #include <array> void Foo() { array<> a; generate(a.begin(),a.end(),rand); sort( ...

  6. php抽象类的简单应用

    抽象类也是面向对象中的重要概念,和接口.继承的概念重要性相当,在面向对象的开发中,所有的对象都是通过类来描述的,但是反过来,并不是所有类都是用来描绘对象的,广义上讲如果一个类中没有足够信息来描述一个具 ...

  7. Greedy:Protecting the Flowers(POJ 3262)

    保护花朵 题目大意:就是农夫有很多头牛在践踏花朵,这些牛每分钟破坏D朵花,农夫需要把这些牛一只一只运回去,这些牛各自离牛棚都有T的路程(有往返,而且往返的时候这只牛不会再破坏花),问怎么运才能使被践踏 ...

  8. HDU 3835 R(N)

    R(N) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. [Android Memory] android 警告:Exported activity does not require permission

    在一个应用程序中添加了多个antivity后,在manifest.xml文件中会除了主Activity外,其它的Activity属性中都会有个警告: Exported activity does no ...

  10. [Android Memory] Android Zipalign zip对齐优化app程序

    转载地址:http://www.cnblogs.com/xirihanlin/archive/2010/04/12/1710164.html 参考文章:http://www.cnblogs.com/l ...