C# 泛型中的数据类型判定与转换
提到类型转换,首先要明确C#中的数据类型,主要分为值类型和引用类型:
1.常用的值类型有:(struct)
整型家族:int,byte,char,short,long等等一系列
浮点家族:float,double,decimal
孤独的枚举:enum
孤独的布尔:bool
2.常用的引用类型有:
string,class,array,delegate,interface
值得注意的是,无论是值类型还是引用类型,在C#中都派生于object,没错,这家伙就是万恶之源!
正是因为有了这一特性,于是我们才能通过装箱和拆箱愉快地将这些数据类型在值类型,object,引用类型间反复横跳。
当然了,无论是装箱和拆箱,对于性能都是有消耗的,不到万不得已的时候尽量不要用(虽然我才不管这些,只要我用的爽就行了233)
虽然一般不提倡用object类型作为函数参数,取而代之使用泛型成为首选,那么如何判断泛型参数的具体数据类型并进行有效转换呢?
比如下面的例子:
[System.Serializable]
public struct Property<T> where T : struct
{
public string Label { get; }
public T Value { get; }
public PropertyType Type { get; }
public Property(string label, T value, PropertyType type = PropertyType.Sub)
{
Label = label;
Value = value;
Type = type;
} public static Property<T> operator +(Property<T> a, Property<T> b)
{
var prop = new Property<T>();
if (a.Label == b.Label && a.Type == b.Type)
{
//怎么知道这个值到底是int还是float...
}
return prop;
}
}
public enum PropertyType
{
Main,
Sub
}
定义了一个名叫「属性」的结构体,包含标签,具体值和属性类别(是主属性还是副属性),并使用泛型约束数据为值类型。
现在想要快速对这个结构体进行加法操作,于是增加操作符重载函数,方便愉快的对两个属性的值相加,但问题是泛型类型是无法强转为任何一种数据类型的,直接则相加更是不可能。
这时就想到了以object类型作为桥梁,进行具体的类型判定与转换:
public static Property<T> operator +(Property<T> a, Property<T> b)
{
if (a.Label == b.Label && a.Type == b.Type)
{
object tempa = a.Value;
object tempb = b.Value; object add;
if (tempa is int)
{
add = (int)tempa + (int)tempb;
}
else if (tempa is float)
{
add = (float)tempa + (float)tempb;
}
//...其他类型
else
{
return new Property<T>();
} return new Property<T>(a.Label, (T)add, a.Type);
}
return new Property<T>();
}
判定类型时可以使用is关键字,也可直接取得值的类型或泛型类型进行判定:
if (tempa.GetType() == typeof(float))
{ }
//or
if (typeof(T) == typeof(float))
{ }
上面的方案虽然可以解决类型转换的需求,但频繁的拆箱和装箱以及类型判定对性能的还是有一定影响,而且如果每一种类型都写进if-else,看上去像千层塔一般难受。是时候轮到dynamic登场了。
.Net 4.0 以后开始支持动态数据类型,也就是dynamic关键字,dynamic可以被赋值为任何一种类型的值,当然也包括泛型。
需要注意的是,dynamic关键字并不会在程序编译的时候进行校验,而是只在运行时动态判定,所以使用的时需要格外小心。
当然了,多次运行时的性能要远远高于装箱和拆箱,而且书写起来也是相当简洁美观:
public static Property<T> operator +(Property<T> a, Property<T> b)
{
if (a.Label == b.Label && a.Type == b.Type)
{
dynamic x1 = a.Value;
dynamic x2 = b.Value;
return new Property<T>(a.Label, (T)(x1 + x2), a.Type);
}
return new Property<T>();
}
可以直接执行相加操作,但如果实际传入的两个数据类型并不能相加如bool,则会在运行时报错;当然了,如果想进一步防止安全,还可以增加更多的类型判定语句,如:
public static Property<T> operator +(Property<T> a, Property<T> b)
{
if (a.Label == b.Label && a.Type == b.Type)
{
if (typeof(T) != typeof(bool) && typeof(T)!=typeof(Enum))
{
dynamic x1 = a.Value;
dynamic x2 = b.Value;
return new Property<T>(a.Label, (T)(x1 + x2), a.Type);
}
}
return new Property<T>();
}
补充一句,dynamic关键字在Unity中可能会报错,因为Unity默认用的是.Net Api为2.0版本,需要升级为4.0之后的版本才能使用该关键字,具体设置如下:

下面做一个简单测试:
using UnityEngine; public class MicrosoftCSharpTest : MonoBehaviour
{
void Start()
{
dynamic a = 5.1f;
dynamic b = ;
Debug.Log(a + b); var hp1 = new Property<int>("Hp", );
var hp2 = new Property<int>("Hp", );
var hp = hp1 + hp2;
Debug.Log(hp.Label + " : " + hp.Value); var miss1 = new Property<float>("MissRate", .1f);
var miss2 = new Property<float>("MissRate", .05f);
var miss = miss1 + miss2;
Debug.Log(miss.Label + " : " + miss.Value);
}
}

C# 泛型中的数据类型判定与转换的更多相关文章
- JavaScript中基本数据类型之间的转换
在JavaScript中共有六种数据类型,其中有五种是基本数据类型,还有一种则是引用数据类型.五种基本数据类型分别是:Number 数值类型.String 字符串类型.Boolean 布尔类型, nu ...
- js中的数据类型隐式转换的三种情况
js的数据类型隐式转换主要分为三种情况: 1. 转换为boolean类型 2. 转换为number类型 3. 转换为string类型 转换为boolean类型 数据在 逻辑判断 和 逻辑运算 之中会隐 ...
- C++中不同数据类型的互相转换
1.string --> char * char * p = (char*)str.c_str(); 2.char * -->string char *p = "aaa& ...
- SQL Server有意思的数据类型隐式转换问题
写这篇文章的时候,还真不知道如何取名,也不知道这个该如何将其归类.这个是同事遇到的一个案例,案例比较复杂,这里抽丝剥茧,仅仅构造一个简单的案例来展现一下这个问题.我们先构造测试数据,如下所示: CRE ...
- swift 中数据类型那个的转换
在swift中关于数据类型的转换,如果参数是可选类型? 那么打印或者转换的结果 会带有Optional 字样,,
- Oracle中的数据类型和数据类型之间的转换
Oracle中的数据类型 /* ORACLE 中的数据类型: char 长度固定 范围:1-2000 VARCHAR2 长度可变 范围:1-4000 LONG 长度可变 最大的范围2gb 长字符类型 ...
- java中的、标识符、运算符以及数据类型之间的转换。
---恢复内容开始--- 数据类型之间的转换: 1:自动转换:就是不用说出要转换成什么类型,由java中的虚拟机自动将小数据类型转换成大数据类型,但大数据中的数据精度有可能被破坏. 2:强制转换:强制 ...
- C#中数据类型的安全转换(is,as)
原文 C#中数据类型的安全转换(is,as) 下面代码中,不能装箱,在强制类型转换时出错,因为之前 c 是 class 类型,而却要把它转换为 int 类型,这是不可以的.虽然编译器能通过编译,但是 ...
- js中的数据类型及其转换
Js中的数据类型 Js中的数据类型一共有六种,即number,string,boolean,underfine,null,object. 一,number Number数据类型指的是数字,可以为整型, ...
随机推荐
- cc23b_demo-函数对象c++ 调用操作符的重载与函数对象-//用模板定义一元谓词、代码示范
//用模板定义一元谓词. #include <iostream> #include <vector> #include <algorithm> using name ...
- Java学习笔记6(集合类)
集合类 集合按照其存储结构可以分为两大类,即单列集合Collection和双列集合Map. Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,有List和Set两个重要子接口 ...
- 万级TPS亿级流水-中台账户系统架构设计
万级TPS亿级流水-中台账户系统架构设计 标签:高并发 万级TPS 亿级流水 账户系统 背景 业务模型 应用层设计 数据层设计 日切对账 背景 我们需要给所有前台业务提供统一的账户系统,用来支撑所有前 ...
- DataOutputStream是用来处理什么类型数据的
FileOutputStream f=new FileOutputStream(new File("sa.txt")); DataOutputStream do=new DataO ...
- Win8.1卸载64位Oracle Database 11g的详细图文步骤记录
Oracle Database 11g在Win8 上的卸载过程记录. Step1停用oracle服务:进入计算机管理/任务管理器,在服务中,找到oracle开头的所有服务,右击选择停止: Step2 ...
- SpringBoot--使用Mybatis分页插件
1.导入分页插件包和jpa包 <dependency> <groupId>org.springframework.boot</groupId> <artifa ...
- 基于jQuery的打字机函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- LeetCode65. 有效数字
这题完美的诠释了什么叫"面向测试用例编程".由于要考虑的情况很多,所以基本的思路是先根据给出的测试用例写出规则判断无效的情况,然后再根据提交的错误对剩下的情况进行特判,如果不满足所 ...
- 6.30集训模拟赛4(炸裂的一天qwq)
T1浇水: 题目描述 在一条长n米,宽m米米的长方形草地上放置着k个喷水装置.假设长方形草地的坐标范围为[ 0 , 0 ] ~ [ n , m ],那么第 i 个喷水装置的位置为(ai,m/2),也就 ...
- 《算法笔记》6.6小节 问题 A: 任务调度
这道题我一开始看到的时候,想到的是拓补排序,可是这么菜又这么懒的我怎么可能用呢,既然出现在优先队列里面,那么久一定和他有关了 可是并没有使用优先队列 思路: 对于这道题,我们肯定是对他们定义优先级,然 ...