c# 判断 泛型t 类型_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类型作为函数参数,取而代之使用泛型成为首选,那么如何判断泛型参数的具体数据类型并进行有效转换呢?

比如下面的例子:

1 [System.Serializable]2 public struct Property where T : struct

3 {4 public string Label { get; }5 public T Value { get; }6 public PropertyType Type { get; }7 public Property(string label, T value, PropertyType type =PropertyType.Sub)8 {9 Label =label;10 Value =value;11 Type =type;12 }13

14 public static Property operator +(Property a, Propertyb)15 {16 var prop = new Property();17 if (a.Label == b.Label && a.Type ==b.Type)18 {19 //怎么知道这个值到底是int还是float...

20 }21 returnprop;22 }23 }

1 public enumPropertyType2 {3 Main,4 Sub5 }

定义了一个名叫「属性」的结构体,包含标签,具体值和属性类别(是主属性还是副属性),并使用泛型约束数据为值类型。

现在想要快速对这个结构体进行加法操作,于是增加操作符重载函数,方便愉快的对两个属性的值相加,但问题是泛型是无法强转为任何一种非object数据类型,直接相加则更是不可能。

这时就想到了以object类型作为桥梁,进行具体的类型判定与转换:

1 public static Property operator +(Property a, Propertyb)2 {3 if (a.Label == b.Label && a.Type ==b.Type)4 {5 object tempa =a.Value;6 object tempb =b.Value;7

8 objectadd;9 if (tempa is int)10 {11 add = (int)tempa + (int)tempb;12 }13 else if (tempa is float)14 {15 add = (float)tempa + (float)tempb;16 }17 //...其他类型

18 else

19 {20 return new Property();21 }22

23 return new Property(a.Label, (T)add, a.Type);24 }25 return new Property();26 }

判定类型时可以使用is关键字,也可直接取得值的类型或泛型类型进行判定:

1 if (tempa.GetType() == typeof(float))2 {3

4 }5 //or

6 if (typeof(T) == typeof(float))7 {8

9 }

上面的方案虽然可以解决类型转换的需求,但频繁的拆箱和装箱以及类型判定对性能的还是有一定影响,而且如果每一种类型都写进if-else,看上去像千层塔一般难受。是时候轮到dynamic登场了。

.Net 4.0 以后开始支持动态数据类型——也就是dynamic关键字;令人兴奋的是,dynamic可以被赋值为任何一种类型的值,当然也包括泛型。

然而值得注意的是,dynamic关键字并不会在程序编译的时候进行校验,而只在运行时动态判定,所以使用的时需要格外小心。

当然了,多次运行时的性能要远远高于装箱和拆箱,而且书写起来也是相当简洁美观(¯﹃¯):

1 public static Property operator +(Property a, Propertyb)2 {3 if (a.Label == b.Label && a.Type ==b.Type)4 {5 dynamic x1 =a.Value;6 dynamic x2 =b.Value;7 return new Property(a.Label, (T)(x1 +x2), a.Type);8 }9 return new Property();10 }

可以直接执行相加操作,但如果实际传入的两个数据类型并不能相加如bool,则会在运行时报错;当然了,如果想进一步防止安全,还可以增加更多的类型判定语句,如:

1 public static Property operator +(Property a, Propertyb)2 {3 if (a.Label == b.Label && a.Type ==b.Type)4 {5 if (typeof(T) != typeof(bool) && typeof(T)!=typeof(Enum))6 {7 dynamic x1 =a.Value;8 dynamic x2 =b.Value;9 return new Property(a.Label, (T)(x1 +x2), a.Type);10 }11 }12 return new Property();13 }

补充一句,dynamic关键字在Unity中可能会报错,因为Unity默认用的是.Net Api为2.0版本,需要升级为4.0之后的版本才能使用该关键字,具体设置如下:

下面做一个简单测试:

1 usingUnityEngine;2

3 public classMicrosoftCSharpTest : MonoBehaviour4 {5 voidStart()6 {7 dynamic a = 5.1f;8 dynamic b = 3;9 Debug.Log(a +b);10

11 var hp1 = new Property("Hp", 41);12 var hp2 = new Property("Hp", 5);13 var hp = hp1 +hp2;14 Debug.Log(hp.Label + ":" +hp.Value);15

16 var miss1 = new Property("MissRate", .1f);17 var miss2 = new Property("MissRate", .05f);18 var miss = miss1 +miss2;19 Debug.Log(miss.Label + ":" +miss.Value);20 }21 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值