zoukankan      html  css  js  c++  java
  • C#中的explicit和implicit了解一下吧

    今天在研究公司项目框架的时候看到了下面的用法,public static implicit operator JsonData(int data);。貌似很久没用过这种隐式转换的写法了,因此重新温习一下C#中转换相关的知识。

    作者:依乐祝
    原文地址:https://www.cnblogs.com/yilezhu/p/10898582.html

    implicit

    implicit 关键字用于声明隐式的用户自定义的类型转换运算符。 如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换。

    使用隐式转换操作符之后,在编译时会跳过异常检查,所以隐式转换运算符应当从不引发异常并且从不丢失信息,否则在运行时会出现一些意想不到的问题。

    示例

    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 类中定义运算符:

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

    如下所示,调用用户定义的转换运算符来强制转换:

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

    此转换运算符从源类型转换为目标类型。 源类型提供转换运算符。 不同于隐式转换,显式转换运算符必须通过转换的方式来调用。 如果转换操作会导致异常或丢失信息,则应将其标记为 explicit。 这可阻止编译器静默调用可能产生意外后果的转换操作。

    省略转换将导致编译时错误 CS0266。

    有关详细信息,请参阅使用转换运算符

    示例

    下面的示例提供了 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);
            }
        }
    }
    /*
    输出:
    转换已完成
    */
    

    参考资料

  • 相关阅读:
    协程greenlet与gevent模块
    进程通信和数据共享两种方式
    创建进程的两个方式
    queue队列吃包子
    queue队列是并发利器
    创建线程方式
    threading线程进程
    socketserver实现多用户并发聊天
    socket实现图片读取
    ZYB's Biology
  • 原文地址:https://www.cnblogs.com/yilezhu/p/10898582.html
Copyright © 2011-2022 走看看