格物致知 《Effective C#》读书笔记--验证类型转换

来源:互联网 发布:maven mysql jdbc驱动 编辑:程序博客网 时间:2024/05/17 01:53

 

as看起来很好用的样子,不会抛出异常,只要根据返回值是否为null来做不同的处理就可以了。但是它也不是万金油,以下的情况as就不适用:


①值类型


比如:


    double d = 100.0;

int valueType = d as int;


这两句代码就直接通不过编译,给出的原因是:as 运算符必须用于引用类型或可以为 null 类型(“int”是一种不可以为 null 值的类型)


想一下也合理,as在失败时会返回null,而值类型是不可以为null的(INullable除外)。


由上面的出错信息也可以看出来,as只可以作用于引用类型。


但是也并非所有值类型都适用,存在于一条继承链上的自不必说。但是自定义类型转换呢?


②自定义类型转换


假设有两个类定义如下:


class ClassOne

    {

        private int filedOne;

        public int FiledOne

        {

            get { return filedOne; }

            set { filedOne = value; }

        }

        public static explicit operator ClassTwo(ClassOne co)

        {

            return new ClassTwo { FiledTwo = co.FiledOne };

        }

    }

    class ClassTwo

    {

        private int filedtwo;

        public int FiledTwo

        {

            get { return filedtwo; }

            set { filedtwo = value; }

        }

}


ClassOne中定义了向ClassTwo的转换。


试用一下:


            ClassOne co = new ClassOne { FiledOne=10};

            ClassTwo ct = (ClassTwo)co;


    这样是没问题的,但是再写下面一句:


ct = co as ClassTwo;


就会报告:无法通过引用转换、装箱转换、取消装箱转换、包装转换或 Null 类型转换将类型“CastAsIs.ClassOne”转换为“CastAsIs.ClassTwo”


由此可见as对于自定义类型转换不感冒。


实际上,foreach内部也是使用的强制类型转换的,看下面:


            ClassOne[] arr = 

            new ClassOne { FiledOne = 1 }, 

             new ClassOne { FiledOne = 2 } };


            foreach (ClassTwo item in arr)

            {

                Console.WriteLine(item.FiledTwo.ToString());

        }


这段代码编译和运行都没问题(把arr中的ClassOne强制转换为ClassTwo自然没问题),但是如果改写成下面这样:


            foreach (ClassTwo item in arr as IEnumerable)

            {

                Console.WriteLine(item.FiledTwo.ToString());

        }


就会报告一个InvalidCastException,原因就是IEnumerator.Current()返回的是Object类型,而在foreach中试图将Object转化为ClassTwo就会出错。