C#中implicit和explicit

2024-02-14 06:04

本文主要是介绍C#中implicit和explicit,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

理解:

以类似重载操作符的形式定义用于类型转换的函数

前者类型转换时候直接写等号赋值语法,后者要加目标类型的强制转换

stirng str -> object o -> int a 可以 int a = (int)(str as object)转换通过编译但没有转换逻辑所以运行会报错,explicit就可以解决这个问题,类似于dart语言中的  源类型对象.to目标类型() 的意思.

什么是隐式转换?

int i = 1;

double d = i;

什么是显式转换?

double d = 1;

int i = (int)d

implicit

隐式转换,相当于封箱操作如: int i = 1; object obj = i;

如果不理解封箱可以换个例子: int i = 1; double d = i;

double的可取值范围包含了int的全部可取值范围,所以可以int->double隐式转换

explicit

显式转换,相当于拆箱操作如: object obj = 1; int i = (int)obj;

如果不理解封箱可以换个例子: double i = 1; int i = (int) d;


为什么有显式和隐式转换?

在C#本身的类型转换中,

int, uint , float之类的都可以隐式转换到double,是因为 double可以不丢失精度的情况下保存int, uint , float之类类型的值

而 double要想转换回到其他数值类型,则有可能丢失精度,所以我们要强制转换,也就是显式的指定转换的方式,即

double d = 1.1;

//int i = d;//这样不可以转换

int i = (double)d; //这样可以转换,但是会丢精度

此时 i 的值为1而不是1.1(向下取整,即Math.Floor()函数执行后再转为int的相同作用.

故,

方便,是隐式转换的主要目的

明确,精确,安全,是显式转换的主要目的


implicit/explicit的用法

固定以 public static implicit/explicit operator 目标类型(源类型 源类型形参)

的方式使用.

假设我们有人民币Rmb和美元Dollar类

评估资产的时候,默认都用Dollar来作为通用单位,当需要换成Rmb或者其他比重比如Krw的时候,需要显式的,明确的知道要转换的目标币种的类型.

比如隐式转换 Rmb->Dollar

public static implicit operator Dollar(Rmb rmb)

{

        //汇率相关的计算

}

再比如显式转换 Dollar->Rmb

public static explicit operator Rmb(Dollar rmb)

{

        //汇率先关的计算

}

使用时,隐式转换直接用Rmb可以直接给Dollar赋值

var rmb = new Rmb();

var dollar = rmb;//可以正常编译通过并在运行时正确转换

var doaalr = new Dollar();

//var rmb = dollar;//不可以通过编译,因为没有实现从dollar到rmb的隐式转换

var rmb = (Rmb)dollar;//可以通过编译并在运行时正确转换.


设计建议:

不管隐式还是显式转换都要保证类型安全不溢出不抛错

隐式转换设计时尽量源类型和目标类型不要有太多的偏差,否则容易造成歧义,如

var person = new Person(){ Id = 1111 };

int id = person; //这种虽然是方便从person中取出Id属性赋值给id,但理解可能会有偏差.

尽管我们可以用

int personId = person; 仍然是有较大的歧义.读代码的人会想id怎么会是一个"人"对象呢?

所以都不如 var id = person.Id来的直观.

显示转换设计时, 语义会更明确, 但必要的类型转换说明不可少.丢不丢精度,等都要写清

由于不像函数ConvertXXXToYYY, src.ToDestType<int>(), src.toInt()等直观的通过名称就知道含义且可以传递各种参数如精度之类的,所以保证类型转换的安全稳定和易维护拓展很重要.


完整示例代码带注释:

新建一个cs文件,直接运行Test方法看看效果吧

Rider截图:

/*implicit:隐式转换explicit:显式转换*/using System.Globalization;namespace CS2TS.Test._1_InTestCSFiles;/// <summary>
///     常量值定义
/// </summary>
public static class Constant
{/// <summary>///     1美元换多少人民币/// </summary>public const double DollarToRmb = 6.5;/// <summary>///     1美元换多少韩元/// </summary>public const double DollarToKrw = 1100;
}/// <summary>
///     人
/// </summary>
public class Person
{/// <summary>///     名字/// </summary>public string Name { get; set; } = "无名氏";/// <summary>///     资产,默认以可隐式转换的美元表示,转换成其他货币需要显式转换标明意图/// </summary>public Dollar Money { get; set; } = new();
}public class Rmb
{public double RmbAmount { get; set; }public static implicit operator Dollar(Rmb rmb){return new Dollar{DollarAmount = rmb.RmbAmount / Constant.DollarToRmb};}public static implicit operator Rmb(Dollar dollar){return new Rmb{RmbAmount = dollar.DollarAmount * Constant.DollarToRmb};}public static explicit operator Krw(Rmb rmb){//先把rmb转换成dollar,然后再转换成krwreturn (Dollar)rmb;}public static explicit operator Rmb(Krw krw){//先把krw转换成dollar,然后再转换成rmbreturn (Dollar)krw;}
}/// <summary>
///     韩元
/// </summary>
public class Krw
{public double KrwAmount { get; set; }/*可以直接用美元换韩元如果换成人民币则需要显式转换*/public static implicit operator Dollar(Krw krw){return new Dollar{DollarAmount = krw.KrwAmount / Constant.DollarToKrw};}public static implicit operator Krw(Dollar dollar){return new Krw{KrwAmount = dollar.DollarAmount * Constant.DollarToKrw};}public static explicit operator Rmb(Krw krw){//先把krw转换成dollar,然后再转换成rmbreturn (Dollar)krw;}public static explicit operator Krw(Rmb rmb){//先把rmb转换成dollar,然后再转换成krwreturn (Dollar)rmb;}
}/// <summary>
///     美元,作为中间货币,人民币和韩元都可以直接换成美元,但是美元要换成什么,需要显式转换
/// </summary>
public class Dollar
{public double DollarAmount { get; set; }public override string ToString(){return DollarAmount.ToString(CultureInfo.InvariantCulture);}
}public class ImplicitAndExplicit
{public static void Test(){#region 小明,美元换韩元和人民币var ming = new Person{Name = "小明",Money = new Dollar{DollarAmount = 1000}};//他想换成韩元的或者人民币的时候,需要显示的转换var rmbOfMing = (Rmb)ming.Money;Console.WriteLine($"小明有{ming.Money.DollarAmount}美元,换成人民币是{rmbOfMing.RmbAmount}元");var krwOfMing = (Krw)ming.Money;Console.WriteLine($"小明有{ming.Money.DollarAmount}美元,换成韩元是{krwOfMing.KrwAmount}元");#endregion#region 小红,人民币换韩元Console.WriteLine("小红只有人民币1000元,但是出国换货币的时候,都是央行的汇率,所以她的人民币要先转换成美元,然后再转换成其他货币");var rmbOfHong = new Rmb{RmbAmount = 1000};var hong = new Person{Name = "小红",// 不需要显示转换,因为Rmb有implicit转换成DollarMoney = rmbOfHong};//需要显示转换,因为Dollar没有implicit转换成Rmbvar krwOfHong = (Krw)hong.Money;Console.WriteLine($"小红有{hong.Money.DollarAmount}美元,换成韩元是{krwOfHong.KrwAmount}元");#endregion#region 小黑,韩元换人民币Console.WriteLine("小黑只有韩元1000元,但是出国换货币的时候,都是央行的汇率,所以她的韩元要先转换成美元,然后再转换成其他货币");var krwOfHei = new Krw{KrwAmount = 1000};var hei = new Person{Name = "小黑",// 不需要显示转换,因为Krw有implicit转换成DollarMoney = krwOfHei};//需要显示转换,因为Dollar没有implicit转换成Rmbvar rmbOfHei = (Rmb)hei.Money;Console.WriteLine($"小黑有{hei.Money.DollarAmount}美元,换成人民币是{rmbOfHei.RmbAmount}元");#endregion#region 统一用Dollar来表示资产Console.WriteLine($"小明有{ming.Money.DollarAmount}美元");Console.WriteLine($"小红有{hong.Money.DollarAmount}美元");Console.WriteLine($"小黑有{hei.Money.DollarAmount}美元");#endregion#region 统一用Rmb来表示资产Console.WriteLine($"小明有{((Rmb)ming.Money).RmbAmount}人民币");Console.WriteLine($"小红有{((Rmb)hong.Money).RmbAmount}人民币");Console.WriteLine($"小黑有{((Rmb)hei.Money).RmbAmount}人民币");#endregion#region 统一用Krw来表示资产Console.WriteLine($"小明有{((Krw)ming.Money).KrwAmount}韩元");Console.WriteLine($"小红有{((Krw)hong.Money).KrwAmount}韩元");Console.WriteLine($"小黑有{((Krw)hei.Money).KrwAmount}韩元");#endregion}
}

这篇关于C#中implicit和explicit的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/707684

相关文章

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

C#从XmlDocument提取完整字符串的方法

《C#从XmlDocument提取完整字符串的方法》文章介绍了两种生成格式化XML字符串的方法,方法一使用`XmlDocument`的`OuterXml`属性,但输出的XML字符串不带格式,可读性差,... 方法1:通过XMLDocument的OuterXml属性,见XmlDocument类该方法获得的xm

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

C#实现添加/替换/提取或删除Excel中的图片

《C#实现添加/替换/提取或删除Excel中的图片》在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观,下面我们来看看如何在C#中实现添加/替换/提取或删除E... 在Excandroidel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭