【C#】【溫故知新】類型轉換之拆箱/裝箱(boxing/unboxing),溢出檢測checked/unchecked,自定義轉換implicit/explicit

裝箱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);
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章