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来的直观.

像public class ArgsInfo内定义一个隐式转换从 string [] 到 ArgsInfo就是一个较好的设计

//一段精简的示例代码,实际设计会比这个健壮,仅为了表示该类和 string[] args较好耦合.

public class ArgsInfo
	{
		private readonly Dictionary<string,string> _args = new();
		public static implicit operator ArgsInfo(string[] args)
		{
			var result = new ArgsInfo();
			foreach (var arg in args)
			{
				var kv = arg.Split('=');
				if (kv.Length == 2)
				{
					result._args[kv[0]] = kv[1];
				}
			}
			return result;
		}

		public override string ToString()
		{
			var sb = new StringBuilder();
			foreach (var (key, value) in _args)
			{
				sb.AppendLine($"{key}={value}");
			}
			return sb.ToString();
		}
	}

	public static void Main(string[] args)
	{
        //就像调用了 var argsInfo = new ArgsInfo(args);
		ArgsInfo argsInfo = args;
		Console.WriteLine(argsInfo);
	}

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

由于不像函数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,然后再转换成krw
		return (Dollar)rmb;
	}

	public static explicit operator Rmb(Krw krw)
	{
		//先把krw转换成dollar,然后再转换成rmb
		return (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,然后再转换成rmb
		return (Dollar)krw;
	}

	public static explicit operator Krw(Rmb rmb)
	{
		//先把rmb转换成dollar,然后再转换成krw
		return (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转换成Dollar
			Money = rmbOfHong
		};
		//需要显示转换,因为Dollar没有implicit转换成Rmb
		var 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转换成Dollar
			Money = krwOfHei
		};

		//需要显示转换,因为Dollar没有implicit转换成Rmb
		var 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
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/386221.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《UE5_C++多人TPS完整教程》学习笔记14 ——《P15 创建我们自己的子系统(Creating Our Own Subsystem)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P15 创建我们自己的子系统&#xff08;Creating Our Own Subsystem&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&…

G85银昆高速宝鸡天台山隧道群荣获交通运输部科技示范工程,北京恒星科通隧道无线通信与广播系统应用于该项目

2023年9月12日&#xff0c;全国交通运输科技示范工程现场推进会在河南省平顶山市召开&#xff0c;会上为全国已通过验收的10项科技示范工程进行了授牌&#xff0c;其中由陕西交控集团负责实施的“秦岭天台山超长隧道群安全绿色科技示范工程”名列其中。 【授牌仪式现场】 据了解…

我让ChatGPT帮我钓妹子,它一口气撩了5000人

来自俄罗斯的一名AI开发者、社交平台TenChat的产品经理 AleksandrZhadan于1月30日在推特上发布了自己的婚讯&#xff0c;他将要与自己的女友Karina Imranovna在今年的8月结婚。令人震惊的是Aleksandr Zhadan介绍的认识女友的窍门-ChatGPT 帮他找到了另一半&#xff0c;并且通过…

vue-进阶语法(四)

目录 v-model原理 v-model应用于组件 sync修饰符 ref 和 $refs&#xff08;重点&#xff09; $nextTick v-model原理 原理&#xff1a;v-model本质上是一个语法糖。例如应用在输入框上&#xff0c;就是 value属性 和 input事件 的合写。 作用&#xff1a;提供数据的双向…

测试西门子博途S7-PLCSIM Advanced V5.0的使用

原创 honeytree 西门子博途S7-PLCSIM Advanced V5.0能支持S7-1500&#xff0c;S7-1500R/H&#xff0c;ET200SP&#xff0c;ET200pro的仿真&#xff0c;用此仿真器可以模拟实际的PLC&#xff0c;用于其他软件的连接&#xff0c;比如上位机软件、触摸屏软件,自己用高级语音开发…

VUE学习之路——列表渲染

<p v-for"item in items">{{ item }}</p>使用v-for进行列表的渲染。 这仅仅是一个简单的demo&#xff0c;使用v-for可以用来遍历数组和对象&#xff0c;具体如下&#xff1a; 注意&#xff1a;遍历数组或对象的时候&#xff0c;&#xff08;&#xff09;…

java客运管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java客运管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&#…

几个好用的 iphone 手机模板贴图样机

整理了几个好用的 iphone 手机模板贴图&#xff0c;分享一下。 关注订阅号「设计师工作日常」&#xff0c;发送关键词 iphone mockup ,获取下载链接。 [1] 原文阅读 我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;求点赞求关注&#xff01;

问题:3【单选题】实现职业理想的一般步骤是()。 #媒体#媒体

问题&#xff1a;3【单选题】实现职业理想的一般步骤是()。 A、创业-立业-择业 B、择业-创业-立业 C、择业-立业-创业 D、立业-择业-创业 参考答案如图所示

Git分支和迭代流程

Git分支 feature分支&#xff1a;功能分支 dev分支&#xff1a;开发分支 test分支&#xff1a;测试分支 master分支&#xff1a;生产环境分支 hotfix分支&#xff1a;bug修复分支。从master拉取&#xff0c;修复并测试完成merge回master和dev。 某些团队可能还会有 reale…

分享76个行业PPT,总有一款适合您

分享76个行业PPT&#xff0c;总有一款适合您 76个行业PPT下载链接&#xff1a;https://pan.baidu.com/s/17zUV16XOg9uBfDTH7sURxw?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。知…

有趣儿的组件(HTML/CSS)

分享几个炫酷的组件&#xff0c;起飞~~ 评论区留爪&#xff0c;继续分享哦~ 文章目录 1. 按钮2. 输入3. 工具提示4. 单选按钮5. 加载中 1. 按钮 HTML&#xff1a; <button id"btn">Button</button>CSS&#xff1a; button {padding: 10px 20px;text-tr…

怎么使用ChatGPT提高工作效率?

怎么使用ChatGPT提高工作效率&#xff0c;这是一个有趣的话题。 相信不同的人有不同的观点&#xff0c;大家的知识背景和从事的工作都不完全相同&#xff0c;所以最终ChatGPT能起到的作用也不一样。 在编程过程中&#xff0c;如果我们要找一个库&#xff0c;我们最先做的肯定…

解决MAC连上wifi或热点却不能上网问题

解决MAC连上wifi或热点却不能上网问题 #新换的mac昨天还能连上wifi&#xff0c;今天就不好使了。 找到连接的wifi点击详细信息&#xff0c;选择TCP/IP 中的配置IPV4 选择关闭

【python学习篇1】python基本语法

一、第一个python程序 在控制台上面输出“你好 python”。 在venv目录下面&#xff0c;新建一个Main1.python的文件夹。 然后在文件当中使用print函数输出一句命令即可。 然后&#xff0c;在Main.py下面&#xff0c;右键一下&#xff0c;运行Main1.py&#xff1a;即可看到下…

港口码头航吊远距离相位测距仪|传感器PHR-120100配置使用说明

港口码头航吊远距离相位测距仪|传感器PHR-120100广泛应用于港口码头、航车、位移监测、形变监测、钢铁、堆垛机、龙门吊等领域。 本文重点介绍港口码头航吊远距离相位测距仪|传感器PHR-120100配置使用说明。 一、布局介绍 二、按键介绍 三、指示灯说明 四、显示屏操作说明 …

片上网络NoC(4)——直连拓扑

目录 一、前言 二、直连拓扑 三、总结 一、前言 本文中&#xff0c;我们将继续介绍片上网络中拓扑相关的内容&#xff0c;主要介绍直连拓扑&#xff0c;在此之前&#xff0c;我们已经介绍过了拓扑的指标&#xff0c;这将是继续阅读本文的基础&#xff0c;还没有了解相关内容…

[WinForm开源]概率计算器 - Genshin Impact(V1.0)

创作目的&#xff1a;为方便旅行者估算自己拥有的纠缠之缘能否达到自己的目的&#xff0c;作者使用C#开发了一款小型软件供旅行者参考使用。 创作说明&#xff1a;此软件所涉及到的一切概率与规则完全按照游戏《原神》(V4.4.0)内公示的概率与规则&#xff08;包括保底机制&…

BUGKU-WEB GET

题目描述 没有提示&#xff0c;就一个get&#xff0c;启动场景看看&#xff1a; 解题思路 显然是PHP语言解读分析代码吧写出你的payload 相关工具 略 解题步骤 进入场景分析代码 $what$_GET[what]; echo $what; if($whatflag) echo flag{****};前两句&#xff1a;使用get…

扩展速度提高了12倍!AWS Lambda 函数重大改进!

Marcia 是 Amazon Web Services 的首席开发倡导者&#xff0c;在软件行业构建和扩展应用程序方面拥有20年的工作经验。她热衷于设计能够充分利用云并拥抱DevOps文化的系统。最近她发表了一篇博文&#xff0c;带来了一个AWS Lambda重大改进&#xff1a;扩展速度提升了 12 倍&…