千家信息网

C#如何实现自定义隐式转换和显式转换

发表于:2025-02-05 作者:千家信息网编辑
千家信息网最后更新 2025年02月05日,这篇文章主要介绍了C#如何实现自定义隐式转换和显式转换,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。基础知识类型转换有2种:隐式转换和
千家信息网最后更新 2025年02月05日C#如何实现自定义隐式转换和显式转换

这篇文章主要介绍了C#如何实现自定义隐式转换和显式转换,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

基础知识

类型转换有2种:隐式转换和显式转换。但是,不管是隐式转换,还是显式转换,都是生成了一个新对象返回的。改变新对象的属性,不会影响老对象!(dynamic对象除外,详情搜索dynamic动态类型。)

自定义隐式/显式转换的方法需要用到几个关键字:implicit(隐式转换)、explicit(显式转换)、operator(操作符)。更多的注意点见下:

  1. 方法必須是static

  2. 使用implicitexplicit

  3. 搭配operator(此也是c#關鍵字,可在類別或結構宣告內多載內建運算子或提供使用者定義的轉換)

  4. 返回值为要转换为的目标类型,但不要在方法上声明,方法名为目标类型。注意:返回值不一定是本类类型。本类型和其他类型之间可以互相转换,只要定义转换方法就行。

  5. 参数为原始类型,方法名为目标类型

  6. 类A到类B的类型转换定义不能在类C中进行(即2个类的转换不能在第3个类中定义),否则会报错:用户定义的转换必须是转换成封闭类型,或者从封闭类型转换。具体查看后面的用户定义的转换必须是转换成封闭类型,或者从封闭类型转换

  7. 不能被virtual/override修饰(不能"覆盖"运算符,因为它们是静态的。)Overriding implicit operators in C#

示例代码

//================定义类型和方法================class Robot{    public int Id { get; set; }    public string Name { get; set; }    public Robot(int id, string name)    {        Id = id;        Name = name;    }    #region 其他类型->本类    //隐式转换    public static implicit operator Robot(string name)    {        return new Robot(101, name);    }    //显式转换    public static explicit operator Robot(int id)    {        return new Robot(id, "miku");    }    #endregion    #region 本类->其他类型    //隐式转换    public static implicit operator string(Robot robot)    {        return robot.Name;    }    //显式转换    public static explicit operator int(Robot robot)    {        return robot.Id;    }    #endregion}//================测试代码================#region 其他类型->本类string gumiStr = "gumi";Robot gumi001 = gumiStr; //隐式转换Console.WriteLine("隐式转换:gumi001 : {0}", JsonConvert.SerializeObject(gumi001));int lukaId = 1004;Robot luka001 = (Robot)lukaId; //显式转换Console.WriteLine("显式转换:luka001 : {0}", JsonConvert.SerializeObject(luka001));#endregion#region 其他类型->本类Robot miku001 = new Robot(1001, "miku10001");//隐式转换string mikuName = miku001;//显式转换int mikuId = (int)miku001;Console.WriteLine("隐式转换:miku001 Name: {0}", mikuName);Console.WriteLine("显式转换:miku001 Id: {0}", mikuId);#endregion

输出结果如下:

隐式转换:gumi001 : {"Id":101,"Name":"gumi"}
显式转换:luka001 : {"Id":1004,"Name":"miku"}
隐式转换:miku001 Name: miku10001
显式转换:miku001 Id: 1001

实际应用

问题

[1,[[2,2],[2,2],[2,2],[2,2]]]

这样一个字符串,如何可以反序列化成一个对象?(如何定义这个类?)

答案

using System;using System.Linq;using System.Collections.Generic;using Newtonsoft.Json;using Newtonsoft.Json.Linq;                                        public class Program{        public static void Main()        {                var json = "[1,[[2,2],[2,2],[2,2],[2,2]]]";                var root = JsonConvert.DeserializeObject(json);                foreach(var ele in root)                {                        if(ele.SingleValue.HasValue)                        {//有值,原始数据为 1                                Console.WriteLine(ele.SingleValue.Value);                        }else                        {//原始数据为 二维数组                                Console.WriteLine(string.Join(" ",ele.Select(x=>string.Join(",",x))));                        }                }                Console.WriteLine(JsonConvert.SerializeObject(root));        }}class Root : List { }[JsonConverter(typeof(CConverter))]class Element : List>{    //该属性,存放 1 。后续可以通过判断该属性是否有值来得知原始数据的情况        public long? SingleValue { get; set; }    //遇到 1 ,隐式转换为 该类型,其中 1 被存放到SingleValue属性        public static implicit operator Element(long d)        {                return new Element { SingleValue = d };        }}public class CConverter : JsonConverter{        public override bool CanConvert(Type objectType)        {                return (objectType == typeof(Element));        }        public override bool CanRead  { get { return false; } }        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)        {                throw new NotImplementedException();        }        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)        {                var ele = value as Element;                var token = ele.SingleValue.HasValue ? JToken.FromObject(ele.SingleValue.Value) : JToken.FromObject(ele.ToList());                token.WriteTo(writer);        }        public override bool CanWrite { get { return true; } }}

报错

用户定义的转换必须是转换成封闭类型,或者从封闭类型转换

这个错误,与封闭类型无关。

是因为有这个限制:类A到类B的类型转换定义不能在类C中进行(即2个类的转换不能在第3个类中定义)

所以对于目标类型是集合类List,我们无法直接定义到它的转换。不过,有2个迂回的方法:

  • 创建个类继承自集合类List,定义到这个子类的转换。上面实际应用中的代码就是这样做的:class Element : List>

  • 创建T1T2的自定义转换,使用时逐个转换:list.Select(p=>(B)p).ToList()

其他

应用和设计

在定義類別時,如果有需要,就可以使用這兩個關鍵字來提供類別一些額外的功能

但在使用時也必須考慮設計上是否合理

例如當兩類別有相關性時是否該提取出父类或是接口來使用,而不是為了方便做了一堆轉換,導致程式撰寫與維護上的困難。

读音

  • 隐式转换:implicit [ɪmˈplɪsɪt] adj.不言明[含蓄]的; 无疑问的,绝对的; 成为一部份的; 内含的;

  • 显式转换:explicit [ɪkˈsplɪsɪt] adj.明确的,清楚的; 直言的; 详述的; 不隐瞒的;

感谢你能够认真阅读完这篇文章,希望小编分享的"C#如何实现自定义隐式转换和显式转换"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

0