【转载】C# 中转换运算符 explicit、implicit、operator、volatile 研究

106 阅读3分钟

原文链接

C# 中转换运算符 explicit、implicit、operator、volatile 研究

正文

C# 中的这个几个关键字:explicitimplicitoperator,估计好多人的用不上,什么情况,这是什么?字面解释:

单词翻译
explicit清楚明白的;易于理解的;(说话)清晰的,明确的;直言的;坦率的;直截了当的;不隐晦的;不含糊的。
implicit含蓄的;不直接言明的;成为一部分的;内含的;完全的;无疑问的。
operator操作人员;技工;电话员;接线员;(某企业的)经营者,专业公司。

说了这么多,其实 explicitimplicit 关键字分别表示 显式的类型转换隐式的类型转换

volatile 关键字指示 一个字段可以由多个同时执行的线程修改,可以保证值的最新。

编译器在优化代码时,可能会把经常用到的代码存在 Cache 里面,然后下一次调用就直接读取 Cache 而不是内存,这样就大大提高了效率。但是问题也随之而来了,在多线程程序中,如果把一个变量放入 Cache 后,又有其他线程改变了变量的值,那么本线程是无法知道这个变化的。它可能会直接读 Cache 里的数据,但是很不幸,Cache 里的数据已经过期了,读出来的是不合时宜的脏数据,这时就会出现bug。用 volatile 声明变量可以很好的解决这个问题。

显式转换

显式转换(强制转换):必须 使用强制运算符,才能执行的转换,在转换过程中可能会 丢失信息转换失败

例如

public class BaseAB { }
public class A : BaseAB { }
public class B : BaseAB { }
//测试
double test = 1.234;
int testInt = (int)test;
Console.WriteLine(testInt); //运算结果1,强制转换数据丢失

try {
    BaseAB ab = new A();
    B b = (B)ab;  //引用强制转换抛出异常 System.InvalidCastException: Unable to cast object of type 'A' to type 'B'.
} catch (Exception ex) {
    Console.WriteLine(ex.ToString());
}

在值类型强制转换的时候,会数据丢失,在引用类型做强制转换的时候会有引发 InvalidCastException 风险,但是可以通过使用 模式匹配 安全的进行强制转换,通过 isas 运算符来检测是否属于特定类型。

模式匹配:给定一个子串,要求在某个字符串中找出与该子串相同的所有子串。例如:A 是字串,BA 是待查找的字符串,要求从 BA 中查找出所有与 A 相同的字串,这个问题就是模式匹配问题。A 是模式,BA 是目标。

例如:

var test = 1.1234;
int testInt = test is int ? (int)test : 0;
Console.WriteLine(testInt);

BaseAB ab = new A();
B b = ab as B;
if (b == null) Console.WriteLine("ab 不是 B类型");

//结果:
//0
//ab 不是 B类型

隐式转换

隐式转换:这种转换是 类型安全 的,不需要特殊处理。

例如:

int i = 123;
double b = i;
Console.WriteLine(b);

A a = new A();
BaseAB baseAB = a;

结果: 123

简单来说就是:小类型转换成大类型的时候隐式转换,大类型转换成小类型用强制转换int > float > double > deca

正题

operator 关键字用于在类或结构声明中 声明运算符。运算符声明可以采用下列四种形式之一:

public static result-type operator unary-operator (type1 param)
public static result-type operator binary-operator (type1 param1, type2 param)
public static implicit operator result-type (type param )
public static explicit operator result-type (type param )
参数说明
result-type结果类型
type,type1,type2参数类型
unary-operator + - ! ~ ++ — true false
binary-operator + - * / % & | ^ << >> == != > < >= <=

介绍了这么多,开始步入正题,讲解 explicitimplicitoperatorexplicitimplicit 都是与 operator 一起操作使用的,operator 关键字用于在类或结构声明中声明运算符。explicit 用于强制转换,implicit 用于隐式转换。

例如:

public struct MeDecimal
{
    private readonly int intV;
    private readonly double doubleV;

    public MeDecimal(int value):this(value,0)
    {
    }

    public MeDecimal(double value):this(0,value)
    {
    }

    public MeDecimal(int intV, double doubleV)
    {
        this.intV = intV;
        this.doubleV = doubleV;
    }

    public static implicit operator int(MeDecimal meDecimal)
    {
        return meDecimal.intV;
    }

    public static explicit operator double(MeDecimal meDecimal)
    {
        return meDecimal.doubleV;
    }

    public static implicit operator MeDecimal(int meDecimal)
    {
        return new MeDecimal(meDecimal);
    }

    public static explicit operator MeDecimal(double meDecimal)
    {
        return new MeDecimal(meDecimal);
    }

    public static MeDecimal operator ++(MeDecimal meDecimal)
    {
        var t = meDecimal.intV + 1;
        var t2 = meDecimal.doubleV + 1;
        var temp = new MeDecimal(t, t2);
        return temp;
    }

    public override string ToString()
    {
        return $"intV:{intV},doubleV:{doubleV}";
    }
}

用法:

MeDecimal d = (MeDecimal)2.1;
Console.WriteLine($"原始数据:{d}");
d++;
double c = (double)d;
int c2 = d;
Console.WriteLine($"int的值:{c2},double的值:{c}");
Console.WriteLine($"{d}");

结果
原始数据:intV:0, doubleV:2.1
int 的值:1, double 的值:3.1
intV:1, doubleV:3.1

像一些类型需要转换的地方或者特殊处理的地方,可以用 explicitimplicit,方便操作。