首页 > 代码库 > 改善C# 程序 的N个建议(1-5)

改善C# 程序 的N个建议(1-5)

  最近有空了,还有本来想趁最近空闲时间深入学习一下java的,但是…(我还没能力去黑java,只能说我用不习惯,有点像用惯Windows 操作系统的人转用其他系统一样,会有些不习惯).而且很长一段时间没写C# 了,加上看到一本《编写高质量代码:改善C#程序的157个建议》还不错,我正好可以回顾一下C#,我是靠C# 入门程序员的.看家本领不能丢啊,所以有了写此系列文章的想法.一下就说多了,切入正题:

  建议1:对String 与值类型进行字符串拼接使用.ToString()在拼接.(string str=”str”+9.ToString())

string str1 = "str" + 9;
string str2 = "str" + 9.ToString();//better

例如上面这两段代码,第一行,需要装箱.第二行则不用装箱.证据如下:

L_0000: nop 
    L_0001: ldstr "str"
    L_0006: ldc.i4.s 9
    L_0008: box int32
    L_000d: call string [mscorlib]System.String::Concat(object, object)
    L_0012: stloc.0 
    L_0013: ldstr "str"
    L_0018: ldc.i4.s 9
    L_001a: stloc.3 
    L_001b: ldloca.s num
    L_001d: call instance string [mscorlib]System.Int32::ToString()
    L_0022: call string [mscorlib]System.String::Concat(string, string)
    L_0027: stloc.1

可以看到第四行,”box”指令.说明发生装箱操作.虽然只有一次装箱操作.对系统整体性能毫无影响.而L_001d 调用了System.Int32.ToString()通过IL中看是调用非托管代码,无法继续跟踪.但是我有代码洁癖,能”干净”点就干净点.

建议2:要清楚如何对自定义类型做类型转换(IP ip = (IP)"192.168.0.1") .

自定义一个IP类:

public class IP:IConvertible,IFormatProvider
        {
            IPAddress value;
            public IP(string ip)
            {
                IPAddress.TryParse(ip, out value);
            }
            public static implicit operator IP(string ip)
            {
                IP iptemp=new IP(ip);
                return iptemp;
            }

            public override string ToString()
            {
                return value.ToString();
            }
            //省略部分代码...
            public bool ToBoolean(IFormatProvider provider)
            {
                throw new InvalidCastException("IP-to-Boolean conversion is not supported.");
            }

            public string ToString(IFormatProvider provider)
            {
                return value.ToString();
            }
            //省略部分代码...

            public object GetFormat(Type formatType)
            {
                return null;
            }
        }

就可以这样调用:

IP ip = new IP ("192.168.0.1");
 ip = (IP)("192.168.0.2");
 bool boolIP = ip.ToBoolean(ip);
 bool boolIP2 = Convert.ToBoolean(ip);

隐式转换需要实现隐式操作符(implicit operator)的方法.如果要转换成基元类型就要实现IConvertible.

  建议3: 强制转型和as ,is 的用法

强制转型一般有两种情况:

1.两种类型依靠转换操作符完成彼此间的转型(如:隐式转换和Convert).

2.子类和父类之间的转型.

第一种情况,建议2 已经详细阐述过了.那个第二种情况应该怎么处理呢?

as ,is 就是C#语言设计师(Anders.Hejlsberg)针对第二种情况进行设计的关键字.

is:判断是否是继承关系(返回bool)

as: 提供父类向子类的转型.如果转型失败,也不会抛出 Exception ,只会返回null.

public static void FatherConvertToSun(Father father)
{
    if(father is sun)
    {   
        Sun sun = father as Sun;
        //省略部分代码....
    }
 }

建议4:基元类型之间的强制转型(值类型转为引用类型).

值类型都提供了Tryparse 和Parse 方法提供转型.测试代码如下:

public static void TestTryParse(string item)
        {
            double number = 0;
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < 1000; i++)
            {
                if (double.TryParse(item, out number) == true)
                {
                    number = 0;
                }
            }
            long time = sw.ElapsedTicks;
            if (double.TryParse(item, out number) == true)
            {
                Console.WriteLine(string.Format("TryParse成功耗时:{0}", time));
            }
            else
            {
                Console.WriteLine(string.Format("TryParse失败耗时:{0}", time));
            }

       }
public static void TestParse(string item)
        {
            Stopwatch sw = Stopwatch.StartNew();
            double number = 0;
            for (int i = 0; i < 1000; i++)
            {
                try
                {
                    number = double.Parse(item);
                }
                catch (Exception ex)
                {
                    number = 0;
                }
            }
            long time = sw.ElapsedTicks;
            if (number != 0)
            {
                Console.WriteLine(string.Format("Parse成功耗时:{0}", time));
            }
            else
            {
                Console.WriteLine(string.Format("Parse失败耗时:{0}", time));
            }
        }

结果如下:

QQ截图20140516220338

TyeParse的效率比Parse 的效率高得多,特别是转型失败的时候.建议:值类型与引用类型之间使用TryParse转型.

建议5:可空值类型的使用环境.

1.从数据库中读取数字可空型字段(decimal,int)时,使用可空类型可以防止把null赋值给值类型报异常.

2.从分布式系统中,服务器需要接收和解析客户端发来的数字型数据.这些数字型数据也很有可能为空.

Nullable<int> i=null;//声明赋值方式1;
int ? n=null;//声明赋值方式2;
int j=n?? 0;//如果n为空将0赋值给j,否则 j=i;

可空类型有一个属性(HasValue)可以判断可空类型是否为null.

 

今天就到这来,明天继续5条建议.