详解C# 泛型中的数据类型判定与转换
- 作者: 怪我过分美丽呵呵
- 来源: 51数据库
- 2021-08-30
提到类型转换,首先要明确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数据类型,直接相加则更是不可能。
这时就想到了以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 = 3;
debug.log(a + b);
var hp1 = new property<int>("hp", 41);
var hp2 = new property<int>("hp", 5);
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# 泛型中的数据类型判定与转换的详细内容,更多关于c# 泛型 数据类型判定与转换的资料请关注其它相关文章!
- C#通过fleck实现wss协议的WebSocket多人Web实时聊天(附源码)
- 团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
- 使用 MSBuild.exe 在发布模式下构建 C# 解决方案
- 当我发布 Web 应用程序时,AfterPublish 脚本不运行
- 构建时 T4 转换的产品仅在下一个构建中使用
- ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
- 新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
- 如何将条件编译符号(DefineConstants)传递给 msbuild
- MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
- NuGet 包还原找不到包,没有源
