.NET之类型转换

说起类型转换大家很容易的就会联想到将int类型转换成float类型或者是将double类型转转成int类型之类的转换。当然这可能是大多数人最先接触到的转换方式,也是最简单的转换方式。所谓转换就是从现有类型的值创建一个新的值,对于大多数面向对象的语言而言,因为多出了"类"这个概念,所以类型转换并不仅仅是基础类型(int、float、string等)之间的转换。.NET作为一个承载平台而言自然是需要提供适应多种情况的类型转换方式的,因此本文就结合自己的理解对.NET下的类型转换作一个简单的总结,如有错误,请各位不吝赐教!

一、.NET自动支持的类型转换

  • 基类型和派生类型之间的相互转换
  • 接口对象和实现接口类型的对象之间的相互转换

.NET除了自动支持基础类型之间的转换外还自动支持以上两种类型之间的转换。

至于基类、派生类和接口等概念想必无须过多赘述了。我们先定义一个简单的IPeople接口以及实现该接口的People类,然后再定义一个继承自People的ChinesePeople类。

public interface IPeople

{

string Name { get; set; }

int Age { get; set; }

}

public class People:IPeople

{

public
string Name { get; set; }

public
int Age { get; set; }

public
int Height { get; set; }

}

public class ChinesePeople : People

{

public
string Country { get; set; }

}

由于.NET已经自动支持了以上两类的转换,因此我们可以作如下操作:

People people = new People();

ChinesePeople chinesePeople = new ChinesePeople();

people = chinesePeople;//派生类隐式转换成基类

chinesePeople = (ChinesePeople)people;//基类显示转换成派生类

IPeople ip = people;//实现接口的对象隐式转换成接口对象

people = (People)ip;//接口对象显示转换成实现接口的对象

以上两种转换都是比较简单的类型转换方式,也是在编程中会经常用到的。

二、基类型之间的转换:Convert

Convert是一个与语言无关的静态类,它为我们提供了一组类似ToXXX()形式的方法使得类型之间的转换变得非常简单。使用起来也很简单,例如:

Note:Convert类官方文档https://msdn.microsoft.com/zh-cn/library/system.convert(v=vs.110).aspx

三、自定义类型之间的转换:implicit(扩大、隐式转换)和explicit(缩小,显示转换)

上文已经说过,通过继承或者实现接口的方式我们可以对类型进行显示或隐式转换,那么问题来了,如果两个类型之间没有继承或者接口实现的关系,要怎么在这两个类型之间进行隐式或者显示转换呢?比如说我们再定义一个类型Dog

public class Dog

{

public
string Name { get; set; }

public
int Age { get; set; }

}

如果不进行任何操作直接将Dog类型的变量转换成People或者ChinesePeople类型的变量编译器肯定会抛出异常,就像下面这样,因为编译器无法将Dog类型的变量隐式或者显示的转换成People类型的变量

大家也可以这样理解,狗和人虽然都是动物,并且两者都有名字、年龄、身高等属性,所以从客观上来讲两者是不同的种类,不做任何操作的话是不能相互转换的。但是从主观来讲,张三做了对不起李四的事,李四可能就会认为张三他不是个人,他是条狗。这种情况是因为张三"做了一些事或者一些操作",所以李四才觉得他"可以"是条狗。下面就引入两个关键字implicit和explixit:

  • Implicit:扩大(隐式)转换,当前类型比目标类型具有更小的范围或成员列表(可以理解为基类比派生类具有更少的成员列表)
  • explicit:收缩(显示)转换,当前类型比目标类型具有更大的范围或成员列表(可以理解为派生类比基类具有更少的成员列表)

首先我们来看implicit关键字,implicit关键字可以定义类型的隐式转换,即如果要从People类型隐式转换成Dog类型的话我们需要对Dog类进行一些操作。

/// <summary>

/// 定义从People类型隐式转换成Dog类型的操作

/// </summary>

/// <param name="people">People类型的变量,保存People类型的数据</param>

public static implicit operator Dog(People people)

{

Dog dog = new Dog();

dog.Name = people.Name;

dog.Age = people.Age;

return dog;

}

上面的操作很简单,就是将People类型的一些数据赋值给Dog类型的变量,有了如上操作,我们就可以将People类型的变量隐式转换成Dog类型的变量而不会发生错误。

同理,一条可爱的小狗在某些人的眼里可能就像自己的亲人一样,因此狗"也可以当作"是人,但是也要做一些额外的"操作",比如给狗穿上一件好看的衣服或者剪个时髦的发型。。。所以狗需要"显示"转换成人。因此我们对People类型进行一些变换使得狗可以显示的转换成人。

public class People : IPeople

{

public
string Name { get; set; }

public
int Age { get; set; }

public
int Height { get; set; }

/// <summary>

/// 定义从Dog类型隐式转换成People类型的操作

/// </summary>

/// <param name="dog">Dog类型的变量,保存Dog类型的数据</param>

public static explicit operator People(Dog dog)

{

People people = new People();

people.Name = dog.Name;

people.Age = dog.Age;

people.Height = 111;

return people;

}

}

有了上面的操作我们就可以将Dog类型变量显示转换成People类型的变量

Note:implicit和explicit两个关键字均是对"目标类型"进行操作,比如要将People类型隐式转换成Dog类型的话就要对Dog类型进行操作

四、IConvertible:自定义类型到CLR基类型之间的转换

上面已经介绍了基类型和自定义类型之间的相互转换,那么问题又来了,怎样把一个自定义类型转换成基类型?这种需求虽然不常见,但.NET作为一个平台而言自然是要尽量满足各种需求的。因此它为我们定义了一个IConvertible接口,该接口定义了向所有基类型转换的方法。

不仅如此,该接口还定义了一个返回实现类型的TypeCode方法以及将该类型转换成另一个类型的通用方法ToType。在实现向基类型转换的方法中我们就可以用到Convert静态类,因此IConvertible接口和Convert静态类的组合使得我们可以方便的定义自定义类型到基类型之间的转换。

Note:IConvertible接口的官方文档https://msdn.microsoft.com/zh-cn/library/system.iconvertible(v=vs.110).aspx

五、TypeConverter

除了上述几种类型转换方式之外,我们还可以通过TypeConverter为自定义类型定义转换器,通过使用TypeConverterAttribute使得自定义类型与转换器相关联。这种方式在WPF中比较常见。使用如下:

1.先定义一个类型转换器,转换器只重写了ConvertFrom和ConvertTo两个方法

public class PeopleConverter : TypeConverter

{

public override
object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object
value)

{

if (value is string)

{

string[] datas = ((string)value).Split(‘ ‘);

People people = new People();

people.Name = datas[0];

people.Age = Convert.ToInt32(datas[1]);

people.Height = Convert.ToInt32(datas[2]);

return people;

}

return base.ConvertFrom(context, culture, value);

}

public override
object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object
value, Type destinationType)

{

if (destinationType == typeof(string))

{

People people = value as People;

return people.Name + " " + people.Age + " " + people.Height;

}

return base.ConvertTo(context, culture, value, destinationType);

}

}

2.为自定义类关联转换器

经过上面两个步骤我们就可以这样来使用转换器:

输出如下:

TypeConverter类的具体用法参照官方文档https://msdn.microsoft.com/zh-cn/library/system.componentmodel.typeconverter(v=vs.110).aspx

时间: 2024-11-06 06:18:57

.NET之类型转换的相关文章

More Effective C++

条款一:指针与引用的区别 指针与引用看上去完全不同(指针用操作符'*'和'->',引用使用操作符'.'),但是它们似乎有相同的功能.指针与引用都是让你间接引用其他对象.你如何决定在什么时候使用指针,在什么时候使用引用呢? 首先,要认识到在任何情况下都不能用指向空值的引用.一个引用必须总是指向某些对象.因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量.相反,如果变量肯定指向一个对象,例如你的设计不允许变量为

Javascript类型转换的规则实例解析

http://www.jb51.net/article/79916.htm 类型转换可以分为隐式转换和显式转换,所谓隐式转换即程序在运行时进行的自动转换,显式转换则是人为的对类型进行强制转换.Javascript的变量是松散类型的,它可以存储Javascript支持的任何数据类型,其变量的类型可以在运行时被动态改变.请看示 例: ? 1 2 3 var n = 10; n = "hello CSSer!"; n = {}; 上面的示例中,首先声明n变量并初始化其值为10(整数类型),接

进制、类型转换、提升

进制 java支持四种进制表示 进制 示例 前缀 备注 十进制 int x = 10;     二进制 int x = 0b10; 0b或0B 计算机储存 八进制 int x = 010; 0 兼容以前程序 十六进制 int x = 0xceaf 0x或0X 0~9,a~f 细节: 一个十六进制位可以表示四个二进制位 当数值位数较多时,可以使用下划线对数字进行隔开,例:1_230_456 字面常量 整数:字面常量为int型,如果要表示long类型的字面常量,使用L或l做后缀,建议使用L,因为字母

第二节 变量 、 基本类型 、 运算符 、 表达式 、 数据 、 类型转换 、 常量

一:变量 定义:在程序运行中随时可以发生变化的量 变量声明:变量的声明只能以数字,字母,下划线,且字母不能开头,同时不能是C#中的关键字. 变量使用:变量必须先声明才能使用,变量赋值必须是对应类型,int age=true:这样就会报错. 二:常量 定义:在程序的生存期内不发生更改的不可变值 常量声明:const关键字  public const int age=10; age在程序内不会变,值一直是10: 三:内置数据类型(数值类型和非数值类型) 数值类型:分为整型和非整型 整型如下图: 非整

03 php 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换,算术运算,比较运算

03 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换, 算术运算,比较运算,逻辑运算,短路现象, 三目运算符,字符型运算: 数据类型 整体划分 标量类型: int, float, string, bool 复合类型: array,     object 特殊类型: null,     resouce 整数类型int, integer 3种整数表示法 十进制写法:123: $n1 = 123; 八进制写法: 0123 $n2 = 0123; 十六进制写法: 0x123 $n3

java 复习 - 数据类型转换

基本数据类型转换两天原则 低精度的值可以直接赋值给高精度的变量,直接变成了高精度 高精度的值不可以直接赋值给低精度的变量. 不同类型变量混合运算之后,得到的结果是精度最高的类型 基本数据类型和字符串之间的转换 基本数据类型转换成字符串 使用String 的valueOf()函数. 使用方法: String.valueOf(各种基本类型)  得到一个字符串.例子如下:  package typeConvertTest; public class TypeConvertTest{  public s

C++:类型转换

5.3 类型转换 5.3.1 系统预定义类型间的转换 1. 隐式转换: 例如: int x=5,y;             y=3.5+x; //系统会自动先将int型的5转换为double型的5.0,在和3.5进行加法运算. 隐式类型转换的主要规则: a.在赋值表达式A=B的情况下,赋值运算符右端B的值需要转换为A的类型后进行赋值. b.当char或short类型变量与int类型变量进行运算时,将char或short类型转换为int类型. c.当两个操作对象类型不一致时,在算术运算前,级别低

基本数据类型转换

自动类型转换:容量小的数据类型自动转换成容量大的数据类型.            char                           int long float double byte     short 一字节是8位,一字是2字节. 有多种类型的数据计算时.系统会将所有的数据类型转换成最大的数据然后进行计算. byte short char之间不会自动转换,他们三者计算会首先转换成int在进行计算. 当把任何基本类型的数据和自负类型的数据进行链接运算(+),得到的是字符类型的数据.

C++强制类型转换操作符 const_cast

const_cast也是一个强制类型转换操作符.<C++ Primer>中是这样描述它的: 1.将转换掉表达式的const性质. 2.只有使用const_cast才能将const性质性质转化掉.试图使用其他三种形式的强制转换都会导致编译时的错误.(添加const还可以用其他转换符,如static_const) 3.除了添加const或删除const特性,使用const_cast符来执行其他任何类型的转换都会引起编译错误.(volatile限定符也包括,不过我不怎么了解,本文主要说const)

Objective-C数据类型、数据类型转换

数据类型 1.Objective-C数据类型可以分为:基本数据类型.对象数据类型和id类型. 2.基本数据类型有:int.float.double和char类型. 3.对象类型就是类或协议所声明的指针类型,例如: NSAutoreleasePool *pool ,其中,NSAutoreleasePool是一个类,NSAutoreleasePool *是它指针类型或叫对象类型. 4.id类型可以表示任何类型,一般只是表示对象类型,不表示基本数据类型,所以刚才的变量可以声明pool也可以声明为id