2016-09-02 14:37:03 w200221626 阅读数 3893

implicit 关键字用于声明隐式的用户定义类型转换运算符。如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换。隐式转换可以通过消除不必要的类型转换来提高源代码的可读性。 但是,因为隐式转换不需要程序员将一种类型显式强制转换为另一种类型,所以使用隐式转换时必须格外小心,以免出现意外结果。 一般情况下,隐式转换运算符应当从不引发异常并且从不丢失信息,以便可以在程序员不知晓的情况下安全使用它们。 如果转换运算符不能满足那些条件,则应将其标记为 explicit。

举个例子

        class A
        {
            public A(float f)
            {
                p = f;
            }
            public float p { get; }

            public static implicit operator A(float f)
            {
                return new A(f);
            }

            public static implicit operator float(A a)
            {
                return a.p;
            }
        }

            //初始化构造函数
            A a = new A(100.12345f);
            //把a对象赋值给f,其实这个时候float已经被重载运算了所以不会报错
            float f = a;
            //把30赋值给a2对象的时候,A类已被重载了
            A a2 = 30;
            richTextBox1.Text += "f是:" + f + "\n";
            richTextBox1.Text += "a2.p是:" + a2.p + "\n";


得到的结果是

f是:100.1235
a2.p是:30

总结:连续介绍了三个关键字operator搭配implicit和explicit,重载运算,类型转换的过程当中都离不开static,explicit需要强制转换而implicit隐试转换类型。

2019-10-30 11:52:55 qq_36230380 阅读数 37

先上代码

using System;

namespace Object

{

    public class Pet {

        public string name;

        public Pet(string name) {

            this.name = name;

        }

        virtual public void Print()

        {

            Console.WriteLine("virtual print: 这是Pet:" + name);

        }

    }

    public class DOG : Pet

    {

        public DOG(string name) : base(name){

        }

        /**

         * 方法重写

         */

        public override void Print()

        {

            Console.WriteLine("print:派生类方法重写!这是DOG:" + name);

            //base.print();

        }

        public static implicit operator DOG(Cat cat) {//隐式转换,没有函数名,DOG是返回值类型

            return new DOG(cat.name);

        }

    }

    public class Cat : Pet

    {

        public Cat(string name) : base(name) {

        }

        /**

         * 方法重写

         */

        public override void Print()

        {

            Console.WriteLine("print:派生类方法重写!这是cat:" + name);

            //base.print();

        }

        public static explicit operator Cat(DOG g)

        {//显式转换,没有函数名,Cat是返回值类型

            return new Cat(g.name);

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            DOG dog = new DOG("tom");

            dog.Print();

            Cat cat = (Cat)dog;

            cat.Print();

            DOG dog2 = cat;

            dog.Print();

        }

    }

}

结果

 

注意,隐式转换是

public static implicit operator + 返回值类型+(参数)

显式转换是

public static explicit operator + 返回值类型+(参数)

 

必须是public+static,必须是public+static,必须是public+static!

没有函数名,没有函数名,没有函数名!

别忘了operator,别忘了operator,别忘了operator!

 

2019-05-21 12:11:00 weixin_30553065 阅读数 15

今天在研究公司项目框架的时候看到了下面的用法,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);
        }
    }
}
/*
输出:
转换已完成
*/

参考资料

转载于:https://www.cnblogs.com/yilezhu/p/10898582.html

2014-07-23 09:20:13 xxdddail 阅读数 3747

在类型转换时常会遇到隐式转换和显式转换。那我们自定义的类型要如何去定义隐式转换和显式转换?我们来看一段代码

public class Rational
    {
        private Int32 _inner_int = 0;

        public Rational()
        {

        }

        public Rational(Int32 num)
        {
            this._inner_int = num;
        }


        public Int32 ToInt32() { return this._inner_int; }

        // Implicitly constructs and returns a Rational from an Int32 
        public static implicit operator Rational(Int32 num)
        {
            return new Rational(num);
        }

        // Explicitly returns an Int32 from a Rational 
        public static explicit operator Int32(Rational r)
        {
            return r.ToInt32();
        }

        public override string ToString()
        {
            //return base.ToString();
            String s = String.Format("{0}", this._inner_int);
            return s;
        }
    }

测试代码

  class Program
    {
        static void Main(string[] args)
        {
            Rational r1 = 10;          
            Console.WriteLine(r1);       

            Int32 i = r1;     
            Console.WriteLine(i);       
            Console.ReadLine();
        }
    }
这时编辑会报错,见下图

从提示可以看到,是因为Int32 i=r1时缺少了显式转换。现在我们添加显示转换,修改后的代码及输出结果如下:

结果正常输出为10.

那为什么会这样呢?究其原因是在Rational转换成 Int32时,指定了explicit(显式的),所以必须要指定转换类型Int32。如果将explicit换成implicit(隐式),原来的代码将可以正常运行。

修改后的Rational

 public class Rational
    {
        private Int32 _inner_int = 0;

        public Rational()
        {

        }

        public Rational(Int32 num)
        {
            this._inner_int = num;
        }


        public Int32 ToInt32() { return this._inner_int; }

        // Implicitly constructs and returns a Rational from an Int32 
        public static implicit operator Rational(Int32 num)
        {
            return new Rational(num);
        }

        // Explicitly returns an Int32 from a Rational 
        public static <span style="color:#ff0000;">implicit</span> operator Int32(Rational r)
        {
            return r.ToInt32();
        }

        public override string ToString()
        {
            //return base.ToString();
            String s = String.Format("{0}", this._inner_int);
            return s;
        }
    }
测试代码及输出结果


可见explicit和implicit影响着类型的显式转换和隐式转换。

其实在Rational r1=10已经执行了隐式转换,对应的转换代码如下:

 // Implicitly constructs and returns a Rational from an Int32 
        public static implicit operator Rational(Int32 num)
        {
            return new Rational(num);
        }
如果将implicit换成explicit,Rational r1=10也将会报错(可以自行测试)。


转载请注明出处:http://blog.csdn.net/xxdddail/article/details/38057563

2019-07-04 20:03:06 cxu123321 阅读数 57

c# implicit explicit关键字(隐式和显式数据类型转换)

implicit关键字用于声明隐式的用户定义类型转换运算符。(explicit反之)explicit则用于显示转换用户自定义类型。
static implicit operator target_type ( source_type identifier ){......}
隐式转换可以通过消除不必要的类型转换来提高源代码的可读性。但是,因为可以在未指定的情况下发生隐式转换,因此必须注意防止令人不愉快的后果。

一般情况下,隐式转换运算符应当从不引发异常并且从不丢失信息,以便可以在不知晓的情况下安全使用它们。如果转换运算符不能满足那些条件,则应将其标记为 explicit 作为显示转换数据。 

下边是在网上找的几个简单例子

例1

复制代码

class Digit
    {
        public Digit(double d) { val = d; }
        public double val;
   
        // 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();
        }
    }

复制代码

例2

复制代码

//基本数据类型到用户自定义类型 
class Distance
{
    private int feet;
    private double inches;

    //默认构造函数 
    public Distance()
    {
        feet = 0;
        inches = 0.0;
    }

    //带有单参数的构造函数              
    public Distance(double metres)
    {
        double f;
        f = 3.28 * metres;
        this.feet = (int)f;
        this.inches = 12 * (f - feet);
    }

    //由一个double隐式构造一个Distance 
    public static implicit operator Distance(double metres)
    {
        return new Distance(metres);
    }

    //由一个Distance显式返回一个double 
    public static explicit operator double(Distance d)
    {
        double metres;
        metres = d.inches / 12 + (double)d.feet;
        return (metres / 3.28);
    }

    public override string ToString()
    {
        return String.Format("{0}英尺{1}英寸 ", this.feet, this.inches);
    }

}

class DistanceDemo
{
    public static void Main()
    {
        Distance d1 = 1.25;
        Console.WriteLine(d1);

        double d = (double)d1;
        Console.WriteLine(d);
    }
}

复制代码

例3

复制代码

using System;

namespace Hunts.Keywords
{
    // 定义一个人民币结构。数据类型转换的语法对于结构和类是一样的
    public struct RMB
    {
        // 注意:这些数的范围可能不能满足实际中的使用
        public uint Yuan;
        public uint Jiao;
        public uint Fen;
        public RMB(uint yuan, uint jiao, uint fen)
        {
            if (fen > 9)
            {
                jiao += fen / 10;
                fen = fen % 10;
            }
            if (jiao > 9)
            {
                yuan += jiao / 10;
                jiao = jiao % 10;
            }
            this.Yuan = yuan;
            this.Jiao = jiao;
            this.Fen = fen;
        }

        public override string ToString()
        {
            return string.Format("¥{0}元{1}角{2}分", Yuan, Jiao, Fen);
        }

        // 一些操作
        public static RMB operator +(RMB rmb1, RMB rmb2)
        {
            return new RMB(rmb1.Yuan + rmb2.Yuan, rmb1.Jiao + rmb2.Jiao, rmb1.Fen + rmb2.Fen);
        }

        public static implicit operator float(RMB rmb)
        {
            return rmb.Yuan + (rmb.Jiao / 10.0f) + (rmb.Fen / 100.00f);
        }

        public static explicit operator RMB(float f)
        {
            uint yuan = (uint)f;
            uint jiao = (uint)((f - yuan) * 10);
            uint fen = (uint)(((f - yuan) * 100) % 10);
            return new RMB(yuan, jiao, fen);
        }

        // more
    }

    class App
    {
        static void Main()
        {
            RMB r1, r2, r3, r4;
            // 记得小学时的某次捐款,我把口袋里藏好的一块钱加6张一毛钱以及13个一分钱的硬币都贡献出去了:(
            r1 = new RMB(1, 6, 13);
            // 其实当时其他人都已经交过了,他们总共交了:
            r2 = new RMB(46, 9, 3);
            // 那么加上我的就是:
            r3 = r1 + r2;
            Console.WriteLine("r3 = {0}", r3.ToString());
            // 隐式转换
            float f = r3;
            Console.WriteLine("float f= {0}", f);
            // 显式转换
            r4 = (RMB)f;
            Console.WriteLine("r4 = {0}", r4.ToString());
            //如果不进行显示转换,将出现错误 CS0266: 无法将类型“float”隐式转换为“Hunts.Keywords.RMB”。存在一个显式转换(是否缺少强制转换?)
            Console.Read();
        }
    }
}

复制代码


出处:http://www.cnblogs.com/chengxiaohui/articles/1914190.html

如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

如果你觉得本篇文章对你有所帮助,请给予我更多的鼓励,求打             付款后有任何问题请给我留言!!!

因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【Jack_孟】!

没有更多推荐了,返回首页