C#中的转换

一、什么是转换

  1. 将一个类型转换为另外一个类型;
  2. 可以是两个值类型之间的转换;
  3. 可以是两个引用类型之间的转换;
  4. 可以是值类型和引用类型之间的转换(拆箱与装箱);
  5. 可以用户自定义转换。
  6. 转换的时候有隐式转换/自动转换和显示转换/强制转换。

C#中的转换_第1张图片 

二、值类型之间的转换

1.隐式转换/自动转换

  1. 范围小的值类型 转 范围大的值类型,不丢失数据精度。
  2. 隐式转换最高位用符号位(二进制补码)进行扩展,保证数值的正负是正确的。
  3. 正数符号位是0,使用0进行扩展的叫做零扩展。
  4. 负数符号位是1,使用1进行扩展的叫做符号扩展。

C#中的转换_第2张图片

 值类型之间的隐式转换关系如下图:

C#中的转换_第3张图片

2.显示转换/强制转换 

  1. 范围大的值类型 转 范围小的值类型,无法保证精度不丢失。
  2. 需要使用强转表达式完成转换。

C#中的转换_第4张图片

 显示转换/强制转换理解示例:

  • ushort范围:0~65535
  • byte范围:0~255
  • 只要希望转换的ushort值小于256,就不会损失数据,否则最高位的数据将丢失(溢出)。

C#中的转换_第5张图片

C#中的转换_第6张图片

 3.值类型之间的转换关系

现在我们应该已经知道,占据较少位的值类型可以隐式转换为占据较多位的值类型。

C#中的转换_第7张图片

 三、溢出检测上下文

在类型转换时,进行检测结果是否溢出的代码片段称为溢出检测上下文。

  1. 如果我们指定一个表达式或一段代码为checked,CLR会在转换产生溢出时抛出一个异常。
  2. 默认溢出检测上下文是不检查,如果不检查,转换将继续而不管是否产生溢出。

1.checked和unchecked运算符

C#中的转换_第8张图片 

 2.checked语句和unchecked语句

checked语句和unchecked语句可以嵌套在任意层次。

C#中的转换_第9张图片

四、引用类型之间的转换 

引用类型转换接受源引用并返回一个指向同一位置的引用,但是把引用“标记”为其他类型。

C#中的转换_第10张图片

 1.隐式转换/自动转换

  1. 类可以隐式转换到它继承链中任何类以及它实现的任何接口。
  2. 所有引用类型可以被隐式转换到object类型。
  3. 任何类型可以隐式转换到它继承的接口。

C#中的转换_第11张图片

 委托可以隐式转换为.NET BCL类和接口。

C#中的转换_第12张图片

ArrayS数组,其中的元素都是Ts类型,可以隐式转换:

        a.  .NET BCL类和接口

        b.  另一个数组ArrayT,其中元素都是Tt类型(当满足下面所有条件可转换)

                i. 两个数组有一样的维度

                ii. 元素Ts和元素Tt都是引用类型,而不是值类型

                iii. 在元素Ts和Tt之间存在隐式转换

C#中的转换_第13张图片

 2.显示转换/强制转换

  1. 从object到任何引用类型的转换
  2. 从基类到它继承的类的转换
  • 无效强制转换

如果将基类强制转换成派生类时,派生类并没有创建对象,就将一个基类对象直接强转为派生类对象,会报InvalidCastException异常(无效强制转换异常)。

C#中的转换_第14张图片 

  • 有效强制转换

第一种情况:派生类转基类,本身是隐式转换,可以但没必要的强制转换。

第二种情况:源引用为null

第三种情况:派生类先转基类,再基类转派生类。(先向上转型,再向下转型) 

C#中的转换_第15张图片

五、值类型和引用类型之间的转换

1.装箱

  1. 含义: 值类型隐式转换成引用类型
  2. 装箱产生一个原始值类型和引用类型副本,每一个都可以独立进行操作。

C#中的转换_第16张图片

  • 任何值类型ValueTypeS都可以被隐式转换为object类型、System.ValueType、或InterfaceT(如果ValueTypeS实现了InterfaceT)

C#中的转换_第17张图片

2.拆箱

  1. 含义:把装箱后的对象转换成值类型的过程。
  2. 拆箱是显示转换。
  3. 尝试将一个值拆箱为非原始类型,会抛出一个InvalidCastException异常。

C#中的转换_第18张图片

六、用户自定义转换

除了标准转换,我们还可以为类和结构定义隐式或显示转换。

  1. 需要public和static修饰
  2. 除了implicit和explicit关键字之外,隐式和显示转换的声明语法是一样的。
  3. 语法格式如下:

C#中的转换_第19张图片

 用户自定义转换的约束:

  1. 只可以为类和结构定义用户自定义转换。
  2. 不能重定义标准隐式转换或强制转换。
  3. 对于相同的源类型S和目标类型T,不能声明隐式转换或强制转换。
  4. 对于源类型S和目标类型T,以下命题为真:

                i.S和T必须是不同类型

                ii.S和T不能通过继承关联

                iii.S和T都不能是接口类型或object类型

                iiii.转换运算符必须是S或T的成员

1.单步用户自定义转换

隐式转换代码示例:

    internal class Person
    {
        public string Name;
        public int Age;

        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }

        //将Person隐式转换为int
        public static implicit operator int(Person person)
        {
            return person.Age;
        }

        //将int类型转换成Person类型
        public static implicit operator Person(int i)
        {
            return new Person("NONE", i);
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            Person bill = new Person("Bill", 25);

            int age = bill;//将bill隐式转换为int类型
            Console.WriteLine("Person Info:{0},{1}",bill.Name,age);

            Person person = 17;//将int类型隐式转换为Person类型
            Console.WriteLine("Person Info:{0},{1}", person.Name, person.Age);
        }

    }

显示转换代码示例:


    internal class Person
    {
        public string Name;
        public int Age;

        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }

        //将Person显式转换为int
        public static explicit operator int(Person person)
        {
            return person.Age;
        }

        //将int类型转换成Person类型
        public static explicit operator Person(int i)
        {
            return new Person("NONE", i);
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            Person bill = new Person("Bill", 25);

            int age = (int)bill;//将bill显式转换为int类型
            Console.WriteLine("Person Info:{0},{1}",bill.Name,age);

            Person person =(Person) 17;//将int类型显式转换为Person类型
            Console.WriteLine("Person Info:{0},{1}", person.Name, person.Age);
        }

    }

2.多步用户自定义转换

在用户自定义转换时,可能存在多种转换组合。

C#中的转换_第20张图片

 代码示例:

    class Employee : Person { }

    class Person 
    {
        public string Name;
        public int Age;

        //将Person对象转换为int
        public static implicit operator int(Person person) 
        {
            return person.Age;
        }

    }
    

    internal class Program
    {
        static void Main(string[] args)
        {
            Employee bill = new Employee();
            bill.Name = "Wakaka";
            bill.Age = 17;

            //1.普通转换:       Employee -->  Person
            //2.用户自定义转换:  Person   -->  int
            //3.普通转换:       int      -->  float
            float fVar = bill;

            Console.WriteLine("Person Info: {0},{1}",bill.Name,fVar);
          
        }

    }

代码图解:

C#中的转换_第21张图片

七、is和as运算符

1. is运算符

 我们可以使用is运算符来检查转换是否会成功,避免盲目转换。

  1. 语法:Expr is TargetType;
  2. is运算符只能用于引用转换,以及拆箱、装箱转换,不能用于用户自定义转换。
    class Employee : Person { }

    class Person 
    {
        public string Name = "光头强";
        public int Age = 25;

    }

    internal class Program
    {
        static void Main(string[] args)
        {
            Employee employee = new Employee();

            Person person;

            if (employee is Person) //检测employee是否能转换为Person类型
            {
                person = employee;
                Console.WriteLine("Person Info: {0},{1}", person.Name,person.Age);
            }
        }
    }

2. as运算符

as运算符和强制运算符类似,但如果转换失败,返回null,而不是抛异常。

  1. 语法:Expr as TargetType;
  2. TargetType是目标类型,必须是引用类型
  3. as运算符只能用于引用转换和装箱转换,不能用于用户自定义转换或到值类型的转换。
    class Employee : Person { }

    class Person 
    {
        public string Name = "光头强";
        public int Age = 25;

    }

    internal class Program
    {
        static void Main(string[] args)
        {
            Employee employee = new Employee();

            Person person;

            person = employee as Person;
            if (person != null) 
            {
                person = employee;
                Console.WriteLine("Person Info: {0},{1}", person.Name,person.Age);
            }
        }
    }

(注:本章学习总结自《C#图解教程》)

 

 

你可能感兴趣的:(C#基础笔记,c#,开发语言,visual,studio)