建议2: 使用默认转型方法

除了字符串操作外,程序员普遍会遇到的第二个问题是:如何正确地对类型实现转型。在上一个建议中,从int转型为string,我们使用了类型int的ToString方法。在大部分情况下,当需要对FCL提供的类型进行转型时,都应该使用FCL提供的转型方法。

这些转型方法包括:

使用类型的转换运算符。

使用类型内置的Parse、TryParse,或者如ToString、ToDouble和ToDateTime等方法。

使用帮助类提供的方法。

使用CLR支持的转型。

下面分别对这些方法进行说明。

1. 使用类型的转换运算符

使用类型的转换运算符,其实就是使用类型内部的一个方法(即函数)。转换运算符分为两类:隐式转换和显式转换(强制转换)。基元类型普遍都提供了转换运算符,如:

int i = ;
float j = ;
j = i; //int到float(Single)存在一个隐式转换
i = (int)j; //float(Single)到int存在,而且必须存在一个显式转换

注意 所谓“基元类型”,是指编译器直接支持的数据类型,即直接映射到FCL中的类型。基元类型包括sbyte、byte、short、 ushort、int、uint、long、ulong、char、float、double、bool、decimal、object、string。

用户自定义的类型也可以通过重载转换运算符的方式来提供这一类转换,代码如下所示:

    class Program
{
static void Main(string[] args)
{
Ip ip = "192.168.0.96";
Console.WriteLine(ip.ToString());
}
} class Ip
{
IPAddress value; public Ip(string ip)
{
value = IPAddress.Parse(ip);
}
public static implicit operator Ip(string ip)
{
Ip iptemp = new Ip(ip);
return iptemp;
} public override string ToString()
{
return value.ToString();
}
}

在上面的代码中:

  1. Ip ip = "192.168.0.96";

提供的就是字符串到类型Ip之间的隐式转换。但是,除非考虑一些初始化值,一般不建议用户对自己的类型重载转换运算符。如果用户自定义的类型之间需要转换,建议从面向对象的角度考虑,因为它们一般都含有某种关系(如继承、实现等)。在这种情况下,就应该使用即将介绍的第四种方法:CLR支持的转型。 不过,我们仍需掌握FCL中的类型,尤其是基元类型之间的转换运算符,以便快速地在基元类型间进行转换。

2. 使用类型内置的Parse、TryParse,或者如ToString、ToDouble、ToDateTime等方法

在FCL中,如果某个类型经常需要进行转型操作,类型自身则会带有一些转型方法。比如从string转型为int,因为其经常发生,所以int本身就提供了Parse和TryParse方法。一般情况下,如果要对某类型进行转型操作,建议先查阅该类型的API文档。

3. 使用帮助类提供的方法

可以使用如System.Convert类、System.BitConverter类来进行类型的转换。

System.Convert提供了将一个基元类型转换为其他基元类型的方法,如ToChar、ToBoolean方法等。值得注意的 是,System.Convert还支持将任何自定义类型转换为任何基元类型,只要自定义类型继承了IConvertible接口就可以。如上文中的Ip 类,如果将Ip转型为string,除了重写Object的ToString方法外,还可以实现IConvertible的ToString方法,代码如 下所示:

  1. class Ip : IConvertible
  2. {
  3. //省略
  4. public bool ToBoolean(IFormatProvider provider)
  5. {
  6. throw new InvalidCastException("Ip-to-Boolean conversion is not supported.");
  7. }
  8. public string ToString(IFormatProvider provider)
  9. {
  10. return value.ToString();
  11. }
  12. //省略
  13. }

继承IConvertible接口必须同时实现其他转型方法,如上文中的ToBoolean,如果不支持此类转型,则应该抛出一个InvalidCastException,而不是一个NotImplementedException。

System.BitConverter提供了基元类型与字节数组之间相互转换的方法,这里不再赘述。

4. 使用CLR支持的转型

CLR支持的转型,即上溯转型和下溯转型。这个概念首先是在Java中提出来的,实际上就是基类和子类之间的相互转换,如图1-1所示。

在进行子类向基类转型的时候支持隐式转换,如Dog显然就是一个Animal;而当Animal转型为Dog的时候,必须是显式转换,因为Animal还可能是一个Cat,代码如下所示:

Animal animal;
Dog dog = new Dog();
animal = dog; //隐式转换,因为Dog就是Animal
//dog = animal; //编译不通过
dog = (Dog)animal; //必须存在一个显式转换

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

编写高质量代码改善C#程序的157个建议——建议2: 使用默认转型方法的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议[1-3]

    原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...

  2. 读书--编写高质量代码 改善C#程序的157个建议

    最近读了陆敏技写的一本书<<编写高质量代码  改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...

  3. 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试

    建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...

  4. 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本

    建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...

  5. 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码

    建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...

  6. 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣

    建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...

  7. 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释

    建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...

  8. 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释

    建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...

  9. 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量

    建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...

  10. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法

    建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...

随机推荐

  1. Browserify使用指南(转)

    让浏览器加载Nodejs模块 目前NPM上有二十多万个NodeJS模块,它们都是通过CMD的方式打包的,除了特定的可以使用CMD模块加载器加载的模块,大部分nodejs模块无法直接使用到浏览器环境中. ...

  2. Redhat下 Apache, php, mysql的默认安装路径

    apache: 如果采用RPM包安装,安装路径应在 /etc/httpd目录下 apache配置文件:/etc/httpd/conf/httpd.conf Apache模块路径:/usr/sbin/a ...

  3. 过河卒(Noip2002)(dp)

    过河卒(Noip2002) 时间限制: 1 Sec  内存限制: 128 MB提交: 7  解决: 6[提交][状态][讨论版][命题人:quanxing] 题目描述 棋盘上A点有一个过河卒,需要走到 ...

  4. Java-Maven-Runoob:Maven Web 应用

    ylbtech-Java-Maven-Runoob:Maven Web 应用 1.返回顶部 1. Maven Web 应用 本章节我们将学习如何使用版本控制系统 Maven 来管理一个基于 web 的 ...

  5. 1120 Friend Numbers

    题意:略. 思路:水题,略. 代码: #include <iostream> #include <string> using namespace std; ; }; int m ...

  6. android滚条简单说明

    先看一下我自己写的布局,电脑屏幕太小,只截取到了一个radiobutton. 先画一个horizontalScrollView,因为我要做水平滚动,然后我需要水平布局,就添加了一个LinearLayo ...

  7. Spring MVC启动时初始化的几个常用方法

    Spring-MVC的应用中,要实现类似的功能,主要是通过实现下面这些接口(任选一,至少一个即可) 一.ApplicationContextAware接口 +? 1 2 3 4 5 6 7 8 9 p ...

  8. js keyup、keypress和keydown事件 详解

    js keyup.keypress和keydown事件  详解 js keyup.keypress和keydown事件都是有关于键盘的事件 当一个按键被pressed 或released在每一个现代浏 ...

  9. socket粘包现象加解决办法

    socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...

  10. java - 判断 字符串是否为空

    java - 判断 字符串是否为空 方法一: 最多人使用的一个方法, 直观, 方便, 但效率很低.1:if(s == null || s.equals(""));方法二: 比较字符 ...