zoukankan      html  css  js  c++  java
  • 一起谈.NET技术,写出优雅简明代码的论题集 Csharp(C#)篇[1] 狼人:

      最近和一些朋友讨论如何写出优雅的代码,我们都很喜欢C#,所以以C#为例。主要一共有三位程序员在一起讨论,为简单起见我用ABC代表我们三个人。

      有时候我们会针对一些代码进行讨论,有时候我们会提出一些观点,有时候我们会一起学习网上一些现有的博客,为了便于大家引用,我给每一个论题都编上号。

      在很多情况下,我们的意见统一,那么我会给大家呈现我们的结论;但是有些情况我们有分歧。

      你可以加入我们的讨论,我非常也希望能够获知你的意见,让我们一起茁壮成长!

      好吧,让我们今天就开始。

      论题一:函数越小越好!

    象鼠  相信绝大部分程序员会认同这一点,维护一个超过100行的函数会让人抓狂。

      我记得我以前修改过一个用cobol写的程序,一个文件超过10万行,我为了进行一个极其小的修改花了3天的时间,而且最后自己也不知道会不会造成什么严重的后果。-- 这已经过去8年了,希望那段代码运行良好。

      到底理想状态下,我们的函数应该不大于多少行?我们三个人的答案是:

      A: 10 行

      B: 15 行

      C: 20 行

      论题二:用 Linq 简化代码

      Linq有时可以帮助我们写出一些非常“人性”的语句。

      下面的这个函数是用于在数据库中插入新的评论:

    public static void Create(IEnumerable<CommentData> Comments, SqlConnection cn)
    {
    // validate params
    if (null == cn) throw new ArgumentNullException("cn");
    if (cn.State != ConnectionState.Open) throw new ArgumentException("Invalid parameter: connection is not open.", "cn");
    if (null == Comments) throw new ArgumentNullException("Comments");
    foreach (CommentData data in Comments)
    {
    if (data.CommentId.HasValue)
    throw new ArgumentNullException("Create is only for saving new data. Call save for existing data.", "data");
    }
    ...

      其中foreach这一部分可以简化为:

    if (Comments.Any(data => data.CommentId.HasValue))
    {
    throw new ArgumentNullException("Create is only for saving new data. Call save for existing data.", "data");
    }

      在这一点上,我们存在分歧,A认为没有必要进行简化,因为原来的已经很明确了;但B认为简化后的代码可读性更强,看上去更加直接。

       论题三:集合初始值

      希望每个人都已经知道C#的这个用法了,直接上一些代码:

      3.1

      原始代码:

    List<int> idsToFind = new List<int>();
    idsToFind.Add(
    1);
    idsToFind.Add(
    2);

      修改后:

    List<int> idsToFind = new List<int> {1, 2};

      3.2

      原始代码:

    var startingPoint = new Point();
    startingPoint.X
    = 5;
    startingPoint.Y
    = 13;

      修改后:

    var startingPoint = new Point() { X = 5, Y = 13 };

      论题四:运用 ?:和??

      据说,有些公司会拿这个来测试入门的程序员:

      4.1

      原始代码:

    if (c != null)
    System.Console.WriteLine(c.Name);
    else
    System.Console.WriteLine(
    "List element has null value.");

      修改后:

    System.Console.WriteLine(c != null ? c.Name : "List element has null value.");

      4.2

      原始代码:

    string name = value;
    if (value == null)
    {
    name
    = string.Empty;
    }

      修改后:

    string name = (value != null) ? value : string.Empty;

      还可以更简单,变成:

    string name = value ?? string.Empty;

      论题五: 运用AS

      原始代码:

    if (employee is SalariedEmployee)
    {
    var salEmp
    = (SalariedEmployee)employee;
    pay
    = salEmp.WeeklySalary;
    // ...
    }

      修改后:

    var salEmployee = employee as SalariedEmployee;
    if (salEmployee != null)
    {
    pay
    = salEmployee.WeeklySalary;
    // ...
    }

      论题六: 运用 using

      using首次出现是在visual studio 2005 中,在这以前,很多程序员晕倒在了释放资源的逻辑中。使用using语句实际上生成的IL代码中是一个try, finally代码块,在finally代码块里释放资源。
      原始代码:
    public IEnumerable<Order> GetOrders()
    {
    var orders
    = new List<Order>();
    var con
    = new SqlConnection("some connection string");
    var cmd
    = new SqlCommand("select * from orders", con);
    var rs
    = cmd.ExecuteReader();
    while (rs.Read())
    {
    // ... 
    }
    rs.Dispose();
    cmd.Dispose();
    con.Dispose();
    return orders;
    }

      这是一段非常丑陋的代码,我们完全迷失在dispose群中,什么时候要调用哪个dispose啊? 天哪? 如果我们用 finally, 可以将代码写为:

    public IEnumerable<Order> GetOrders()
    {
    SqlConnection con
    = null;
    SqlCommand cmd
    = null;
    SqlDataReader rs
    = null;
    var orders
    = new List<Order>();
    try
    {
    con
    = new SqlConnection("some connection string");
    cmd
    = new SqlCommand("select * from orders", con);
    rs
    = cmd.ExecuteReader();
    while (rs.Read())
    {
    // ...
    }
    }
    finally
    {
    rs.Dispose();
    cmd.Dispose();
    con.Dispose();
    }
    return orders;
    }

      看看using到底给我们带来了什么:

    public IEnumerable<Order> GetOrders()
    {
    var orders
    = new List<Order>();
    using (var con = new SqlConnection("some connection string"))
    {
    using (var cmd = new SqlCommand("select * from orders", con))
    {
    using (var rs = cmd.ExecuteReader())
    {
    while (rs.Read())
    {
    // ...
    }
    }
    }
    }
    return orders;
    }
      好多了,对吗? 完全不用再用那一堆的try/finally 代码了,也不用使用一堆的null,为了使代码更轻巧,让我们再做小小修改:
    public IEnumerable<Order> GetOrders()
    {
    var orders
    = new List<Order>();
    using (var con = new SqlConnection("some connection string"))
    using (var cmd = new SqlCommand("select * from orders", con))
    using (var rs = cmd.ExecuteReader())
    {
    while (rs.Read())
    {
    // ...
    }
    }
    return orders;
    }

      未完待继…

  • 相关阅读:
    基于发布/订阅模型的应用程序的主循环设计
    C++使用继承时子对象的内存布局
    安装 CentOS 后的系统配置及软件安装备忘
    环形无锁队列
    并发编程基础
    线程池实现
    Git远程操作
    Unix权限管理
    jquery中,某些写法后来更新导致版本不支持的替代方法
    js相关
  • 原文地址:https://www.cnblogs.com/waw/p/2162991.html
Copyright © 2011-2022 走看看