装箱boxing:

是值类型到引用类型的隐式转换,根据值类型的值,在堆上创建一个完整的引用类型对象,并返回对象的引用。

        int i = 1;       //值类型
        object o = i;    //引用类型,在堆上创建int对象,将i的值赋值给对象,将对象的引用返回给o

装箱操作后,原值类型与新引用类型相互独立,可以单独操作。

        int i = 1;
        object o = i;

        Debug.Log(i + " - " + o);   // 1 - 1

        i = 2;
        o = 3;

        Debug.Log(i + " - " + o);   // 2 - 3

拆箱unboxing:

是引用类型到值类型的显式转换,是把装箱之后的对象转换回值类型。

对象必须拆箱转换为原始类型,否则会报错。

        int i = 1;
        object o = i;

        int j = (int)o;
        Debug.Log(j);   // 1

        string s = (string)o;   //报错(InvalidCastException: Specified cast is not valid.)

溢出检测:

显示转换可能会导致溢出或丢失数据,

关键字checked会检测溢出,并在溢出时抛出异常,

        int intValue = 123456;
        byte byteValue;

        checked
        {
            byteValue = (byte)intValue;
            Debug.Log(byteValue);   // 报错(OverflowException: Arithmetic operation resulted in an overflow.)
        }

关键字unchecked会忽略溢出,(不使用该关键字也是忽略溢出)

        int intValue = 123456;
        byte byteValue;

        byteValue = (byte)intValue;
        Debug.Log(byteValue);       // 64

        unchecked
        {
            byteValue = (byte)intValue;
            Debug.Log(byteValue);   // 64
        }

 自定义隐式/显式转换:

除了标准转换,还可以使用关键字implicit和explicit,为类和结构自定义隐式和显式转换:

public static implicit/explicit operator TargetType(SourceType identifer)

自定义要求:

1. 需要public和static关键字;

2. 只有类和结构可以自定义转换;

3. 不能重定义标准转换;

4.1 源类型与目标类型不能相同;

4.2 源类型与目标类型不能有继承关联;

4.3 源类型与目标类型不能是接口或object类型;

4.4 转换运算符必须是源类型或目标类型的成员;

public class Person
{
    public Person(string _name, int _age)
    {
        name = _name;
        age = _age;
    }

    public string name;
    public int age;

    //隐式转换
    public static implicit operator string(Person person)
    {
        if (person == null)
            return string.Empty;
        return person.name;
    }
    public static implicit operator Person(string name)
    {
        return new Person(name, 0);
    }

    //显示转换
    public static explicit operator int(Person person)
    {
        if (person == null)
            return 0;
        return person.age;
    }
    public static explicit operator Person(int age)
    {
        return new Person(string.Empty, age);
    }
}
    public void TestFunc()
    {
        string name = "xiaoming";

        //隐式转换
        Person person = name;
        Debug.Log(person);

        //显示转换
        int age = (int)person;
        Debug.Log(age);
    }

运算符is/as:

对于引用转换和拆箱装箱转换,可以在转换前使用is运算符,检查转换是否能成功,从而避免程序报错;

as运算符与强制转换运算符类似,只是在转换失败是不会报错,会返回null。

    public class Animal { public string name; }
    public class Dog : Animal { }

    private void Start()
    {
        Dog dog = new Dog() { name = "abc" };

        if (dog is Animal)
        {
            Animal animal = dog as Animal;
            Debug.Log(animal.name);
        }
    }