C#中的explicit和implicit瞭解一下吧

今天在研究公司項目框架的時候看到了下面的用法,public static implicit operator JsonData(int data);。貌似好久沒用過這種隱式轉換的寫法了,所以從新溫習一下C#中轉換相關的知識。html

做者:依樂祝
原文地址:http://www.javashuo.com/article/p-tfkmenyn-u.htmlgit

implicit

implicit 關鍵字用於聲明隱式的用戶自定義的類型轉換運算符。 若是能夠確保轉換過程不會形成數據丟失,則可以使用該關鍵字在用戶定義類型和其餘類型之間進行隱式轉換。程序員

使用隱式轉換操做符以後,在編譯時會跳過異常檢查,因此隱式轉換運算符應當從不引起異常而且從不丟失信息,不然在運行時會出現一些意想不到的問題。express

示例

class Digit
{
    public Digit(double d) { val = d; }
    public double val;
    // ...other members

    // User-defined conversion from Digit to double
    public static implicit operator double(Digit d)
    {
        return d.val;
    }
    //  User-defined conversion from double to Digit
    public static implicit operator Digit(double d)
    {
        return new Digit(d);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Digit dig = new Digit(7);
        //This call invokes the implicit "double" operator
        double num = dig;
        //This call invokes the implicit "Digit" operator
        Digit dig2 = 12;
        Console.WriteLine("num = {0} dig2 = {1}", num, dig2.val);
        Console.ReadLine();
    }
}

隱式轉換能夠經過消除沒必要要的強制轉換來提升源代碼的可讀性。 可是,由於隱式轉換不須要程序員將一種類型顯式強制轉換爲另外一種類型,因此使用隱式轉換時必須格外當心,以避免出現意外結果。 通常狀況下,隱式轉換運算符應當從不引起異常而且從不丟失信息,以即可以在程序員不知曉的狀況下安全使用它們。 若是轉換運算符不能知足那些條件,則應將其標記爲 explicit。 有關詳細信息,請參閱使用轉換運算符安全

explicit顯示轉換

explicit 關鍵字聲明必須經過顯示的調用用戶定義的類型轉換運算符來進行轉換。框架

如下示例定義從 Fahrenheit 類轉換爲 Celsius 類的運算符。 必須在 Fahrenheit 類或 Celsius 類中定義運算符:ide

public static explicit operator Celsius(Fahrenheit fahr)
{
    return new Celsius((5.0f / 9.0f) * (fahr.Degrees - 32));
}

以下所示,調用用戶定義的轉換運算符來強制轉換:ui

Fahrenheit fahr = new Fahrenheit(100.0f);
Console.Write($"{fahr.Degrees} Fahrenheit");
Celsius c = (Celsius)fahr;

此轉換運算符從源類型轉換爲目標類型。 源類型提供轉換運算符。 不一樣於隱式轉換,顯式轉換運算符必須經過轉換的方式來調用。 若是轉換操做會致使異常或丟失信息,則應將其標記爲 explicit。 這可阻止編譯器靜默調用可能產生意外後果的轉換操做。this

省略轉換將致使編譯時錯誤 CS0266。code

有關詳細信息,請參閱使用轉換運算符

示例

下面的示例提供了 FahrenheitCelsius 類,其中每一個類均提供轉換爲其餘類的顯式轉換運算符。

class Celsius
{
    public Celsius(float temp)
    {
        Degrees = temp;
    }
    
    public float Degrees { get; }
    
    public static explicit operator Fahrenheit(Celsius c)
    {
        return new Fahrenheit((9.0f / 5.0f) * c.Degrees + 32);
    }
}

class Fahrenheit
{
    public Fahrenheit(float temp)
    {
        Degrees = temp;
    }
    
    public float Degrees { get; }
    
    public static explicit operator Celsius(Fahrenheit fahr)
    {
        return new Celsius((5.0f / 9.0f) * (fahr.Degrees - 32));
    }
}

class MainClass
{
    static void Main()
    {
        Fahrenheit fahr = new Fahrenheit(100.0f);
        Console.Write($"{fahr.Degrees} Fahrenheit");
        Celsius c = (Celsius)fahr;

        Console.Write($" = {c.Degrees} Celsius");
        Fahrenheit fahr2 = (Fahrenheit)c;
        Console.WriteLine($" = {fahr2.Degrees} Fahrenheit");
    }
}
// 輸出:
// 100 Fahrenheit = 37.77778 Celsius = 100 Fahrenheit

示例

下面的示例定義結構 Digit,它表示單個的十進制數字。 將運算符定義爲從 byteDigit 的轉換,但因爲並不是全部字節均可轉換爲 Digit,所以該轉換應該應用顯式轉換。

struct Digit
{
    byte value;
    public Digit(byte value)
    {
        if (value > 9)
        {
            throw new ArgumentException();
        }
        this.value = value;
    }

    // 定義從byte到Digit的顯示轉換 explicit operator:
    public static explicit operator Digit(byte b)
    {
        Digit d = new Digit(b);
        Console.WriteLine("轉換已完成");
        return d;
    }
}

class ExplicitTest
{
    static void Main()
    {
        try
        {
            byte b = 3;
            Digit d = (Digit)b; // 顯示轉換
        }
        catch (Exception e)
        {
            Console.WriteLine("{0} 捕獲到一成.", e);
        }
    }
}
/*
輸出:
轉換已完成
*/

參考資料

相關文章
相關標籤/搜索