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数据类型指的是数字,可以为整型, ...
随机推荐
- Windows下6款实用软件(强烈推荐!)
Windows下6款实用软件 1.notepads Notepads作为一款编辑器,美观.轻量,功能强大,支持多标签页.Markdown.日常文本编辑.查看,Notepads轻松胜任,如果厌烦了Win ...
- JMETER学习宝典
1. 简介 Apache JMeter是100%纯java桌面应用程序,被设计用来测试客户端/服务器结构的软件(例如web应用程序).它可以用来测试包括基于静态和动态资源程序的性能,例如静态文件,Ja ...
- Java WebService学习笔记 - Axis(一)
WebService 简介 实际开发中,很多系统都是基于历史遗留系统进行开发,有时,这些系统基于不同的语言,如C,C++,C#,java,PHP等等.为了实现历史系统的再利用,或向外部程序暴露调用接口 ...
- Redis SDS 深入一点,看到更多!
1.什么是SDS? Redis 自定的字符串存储结构,关于redis,你需要了解的几点!中我们对此有过简要说明. Redis 底层是用C语言编写的,可是在字符存储上,并未使用C原生的String类型, ...
- CSS布局之盒子模型[一]
每个HTML标签都会生成一个盒模型,盒模型是正常流布局非常重要的概念.盒模型由内边距(padding)+长度(width)+高度(height)+边框(border)+外边距(margin)组成. 1 ...
- mycat增加开机自启
一.安装及配置: 见https://github.com/MyCATApache/Mycat-Server 二.增加开机自启: 1.添加开机自启脚本:vim /etc/init.d/mycat.sh, ...
- sql多列排序
从左到右依次排列,如果出现重复值,则按照右侧的排序规则进行排序: 例如:分数倒序排序,但是遇到重复值,则再按照class_id倒序排 例如:分数倒序排序,没有重复值,进行了正常的排序,则不再按照cla ...
- 跟着阿里学JavaDay07——Java基础语法(五)
我们后面的笔记我,打算直接用程序,加注释进行记录.日后若本人有疑问,可进行网络查询加以整理回复 package com.cionda.JavaDemo.dept; public class JavaD ...
- 部署Redis Cluster 6.0 集群并开启密码认证 和 Redis-cluster-proxy负载
部署Redis Cluster集群并开启密码认证 如果只想简单的搭建Redis Cluster,不需要设置密码和公网访问,可以参考官方文档. 节点介绍 Cluster模式推荐最少有6个节点,本次实验搭 ...
- html5中contenteditable 光标_如何设置光标位置
在js中,光标是一个对象,当你选中某个元素的时候才会出现光标对象.比如:我们点击一个输入框,实际会产生一个选中对象-selection,这个对象我们可以通过indow.getSelection()来获 ...