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);
        }
    }
}
/*
输出:
转换已完成
*/

参考资料

相关文章
相关标签/搜索