服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#类型转换之自定义隐式转换和显式转换

C#类型转换之自定义隐式转换和显式转换

2023-02-24 15:21过千帆 C#

本文主要为大家介绍了一个新的类型转换方法:通过自定义隐式转换,把不一样的数据类型反序列化为一样的数据类型,需要的同学可以参考一下

前言

有时我们会遇到这么一种情况:在json数据里,数组里的数据类型不一致,导致我们不能直接反序列化为目标类型。最终我们只能反序列化为JObject类型,然后通过字符串取值的方式来取出数据。

下面介绍一种新方式:通过自定义隐式转换,把不一样的数据类型反序列化为一样的数据类型。

基础知识

类型转换有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#

示例代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//================定义类型和方法================
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]]]

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

答案

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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<Root>(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<Element> { }
[JsonConverter(typeof(CConverter))]
class Element : List<List<long>>
{
    //该属性,存放 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<T>,我们无法直接定义到它的转换。不过,有2个迂回的方法:

  • 创建个类继承自集合类List<T>,定义到这个子类的转换。上面实际应用中的代码就是这样做的:class Element : List<List<long>>
  • 创建T1T2的自定义转换,使用时逐个转换:list.Select(p=>(B)p).ToList()

其他

应用和设计

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

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

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

读音

  • 隐式转换:implicit [ɪmˈplɪsɪt] adj.不言明[含蓄]的; 无疑问的,绝对的; 成为一部份的; 内含的;
  • 显式转换:explicit [ɪkˈsplɪsɪt] adj.明确的,清楚的; 直言的; 详述的; 不隐瞒的;

到此这篇关于C#类型转换之自定义隐式转换和显式转换 的文章就介绍到这了,更多相关C# 类型转换内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/doThing/p/operator-implicit-explicit-in-csharp.html

延伸 · 阅读

精彩推荐
  • C#详解从零开始---用C#制作扫雷游戏

    详解从零开始---用C#制作扫雷游戏

    这篇文章主要介绍了详解从零开始---用C#制作扫雷游戏,非常具有实用价值,需要的朋友可以参考下...

    喻时耕宇9042022-01-10
  • C#C#中获取数据的方法实例

    C#中获取数据的方法实例

    这篇文章主要给大家介绍了关于C#中获取数据的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    骑着母猪去兜风8732022-10-31
  • C#WPF PasswordBox进行数据绑定方法

    WPF PasswordBox进行数据绑定方法

    有的时候会遇见PasswordBox的Password属性不是依赖属性,因此无法进行数据绑定。本文介绍如何通过添加附加属性解决该问题,有此问题的同学可以参考下本文...

    louzi7932022-11-23
  • C#C#的四种基本数据类型

    C#的四种基本数据类型

    本文主要介绍了C#的四种基本数据类型的相关知识,具有很好的参考价值。下面跟着小编一起来看下吧...

    辰星crystal7112021-12-28
  • C#C#从foreach语句中枚举元素看数组详解

    C#从foreach语句中枚举元素看数组详解

    这篇文章主要给大家介绍了关于C#从foreach语句中枚举元素看数组的相关资料,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来...

    Simen.Net5822022-01-05
  • C#C# JsonHelper 操作辅助类,拿来直接用

    C# JsonHelper 操作辅助类,拿来直接用

    本文总结了一些常用的JSON操作辅助类,包括转换、判断、Ajax异步等操作,希望能帮到大家。...

    果冻布丁喜之郎8942021-11-21
  • C#C# WPF ListView控件的实例详解

    C# WPF ListView控件的实例详解

    这篇文章主要介绍了C# WPF ListView控件的实例详解的相关资料,希望通过本能帮助到大家,让大家掌握这部分内容,需要的朋友可以参考下...

    weixinhum5592022-01-24
  • C#C#使用RichTextBox实现替换文字及改变字体颜色功能示例

    C#使用RichTextBox实现替换文字及改变字体颜色功能示例

    这篇文章主要介绍了C#使用RichTextBox实现替换文字及改变字体颜色功能,结合实例形式洗了C#中RichTextBox组件文字替换及改变字体颜色相关操作技巧,需要的朋友...

    changuncle4642022-03-10