当前位置:编程学习 > C#/ASP.NET >>

C#中As和强制转换的总结

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 = o as MyType;
                if (t != null)
                {
                    ////转换成功
                }
                else
                {
                    ////转换失敗
                }

            }
            catch
            {
                ////异常处理
            }
 

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

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

     Foo1 myFoo;          //// Inherits abstract class.
     Logger myFoo;       //// base class.

    public class Foo1 : Foo
    {
        PRivate Logger _value;

        /// <summary>
        /// 隐式自定义类型转换。
                /// </summary>
        /// <param name="foo1"></param>
        /// <returns></returns>
        public static implicit Operator 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())
            {
                UnityConfigu

补充:软件开发 , C# ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,