C#中explicit与implicit的深入理解
前言
今天在研究公司项目框架的时候看到了下面的用法,publicstaticimplicitoperatorJsonData(intdata);。貌似很久没用过这种隐式转换的写法了,因此重新温习一下C#中转换相关的知识。
explicit和implicit属于转换运算符,如用这两者可以让我们自定义的类型支持相互交换
explicti表示显式转换,如从A->B必须进行强制类型转换(B=(B)A)
implicit表示隐式转换,如从B->A只需直接赋值(A=B)
implicit
implicit关键字用于声明隐式的用户自定义的类型转换运算符。如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换。
使用隐式转换操作符之后,在编译时会跳过异常检查,所以隐式转换运算符应当从不引发异常并且从不丢失信息,否则在运行时会出现一些意想不到的问题。
示例
classDigit
{
publicDigit(doubled){val=d;}
publicdoubleval;
//...othermembers
//User-definedconversionfromDigittodouble
publicstaticimplicitoperatordouble(Digitd)
{
returnd.val;
}
//User-definedconversionfromdoubletoDigit
publicstaticimplicitoperatorDigit(doubled)
{
returnnewDigit(d);
}
}
classProgram
{
staticvoidMain(string[]args)
{
Digitdig=newDigit(7);
//Thiscallinvokestheimplicit"double"operator
doublenum=dig;
//Thiscallinvokestheimplicit"Digit"operator
Digitdig2=12;
Console.WriteLine("num={0}dig2={1}",num,dig2.val);
Console.ReadLine();
}
}
隐式转换可以通过消除不必要的强制转换来提高源代码的可读性。但是,因为隐式转换不需要程序员将一种类型显式强制转换为另一种类型,所以使用隐式转换时必须格外小心,以免出现意外结果。一般情况下,隐式转换运算符应当从不引发异常并且从不丢失信息,以便可以在程序员不知晓的情况下安全使用它们。如果转换运算符不能满足那些条件,则应将其标记为explicit。有关详细信息,请参阅使用转换运算符。
explicit显示转换
explicit关键字声明必须通过显示的调用用户定义的类型转换运算符来进行转换。
以下示例定义从Fahrenheit类转换为Celsius类的运算符。必须在Fahrenheit类或Celsius类中定义运算符:
publicstaticexplicitoperatorCelsius(Fahrenheitfahr)
{
returnnewCelsius((5.0f/9.0f)*(fahr.Degrees-32));
}
如下所示,调用用户定义的转换运算符来强制转换:
Fahrenheitfahr=newFahrenheit(100.0f);
Console.Write($"{fahr.Degrees}Fahrenheit");
Celsiusc=(Celsius)fahr;
此转换运算符从源类型转换为目标类型。源类型提供转换运算符。不同于隐式转换,显式转换运算符必须通过转换的方式来调用。如果转换操作会导致异常或丢失信息,则应将其标记为explicit。这可阻止编译器静默调用可能产生意外后果的转换操作。
省略转换将导致编译时错误CS0266。
有关详细信息,请参阅使用转换运算符。
示例
下面的示例提供了Fahrenheit和Celsius类,其中每个类均提供转换为其他类的显式转换运算符。
classCelsius
{
publicCelsius(floattemp)
{
Degrees=temp;
}
publicfloatDegrees{get;}
publicstaticexplicitoperatorFahrenheit(Celsiusc)
{
returnnewFahrenheit((9.0f/5.0f)*c.Degrees+32);
}
}
classFahrenheit
{
publicFahrenheit(floattemp)
{
Degrees=temp;
}
publicfloatDegrees{get;}
publicstaticexplicitoperatorCelsius(Fahrenheitfahr)
{
returnnewCelsius((5.0f/9.0f)*(fahr.Degrees-32));
}
}
classMainClass
{
staticvoidMain()
{
Fahrenheitfahr=newFahrenheit(100.0f);
Console.Write($"{fahr.Degrees}Fahrenheit");
Celsiusc=(Celsius)fahr;
Console.Write($"={c.Degrees}Celsius");
Fahrenheitfahr2=(Fahrenheit)c;
Console.WriteLine($"={fahr2.Degrees}Fahrenheit");
}
}
//输出:
//100Fahrenheit=37.77778Celsius=100Fahrenheit
示例
下面的示例定义结构Digit,它表示单个的十进制数字。将运算符定义为从byte到Digit的转换,但由于并非所有字节都可转换为Digit,因此该转换应该应用显式转换。
structDigit
{
bytevalue;
publicDigit(bytevalue)
{
if(value>9)
{
thrownewArgumentException();
}
this.value=value;
}
//定义从byte到Digit的显示转换explicitoperator:
publicstaticexplicitoperatorDigit(byteb)
{
Digitd=newDigit(b);
Console.WriteLine("转换已完成");
returnd;
}
}
classExplicitTest
{
staticvoidMain()
{
try
{
byteb=3;
Digitd=(Digit)b;//显示转换
}
catch(Exceptione)
{
Console.WriteLine("{0}捕获到一成.",e);
}
}
}
/*
输出:
转换已完成
*/
参考资料
- explicit
- operator(C#Reference)
- Howto:ImplementUser-DefinedConversionsBetweenStructs
- implicit
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。