【问题标题】:Best way to write a simple boolean method with good C# syntax用良好的 C# 语法编写简单布尔方法的最佳方法
【发布时间】:2011-02-24 04:01:05
【问题描述】:

大家好,我好像到处都有这类方法。

下面的方法想要完成这些简单的任务:

  1. 打开数据库连接(IntLMPDB 对象)
  2. 从一个小的 DB 表中读取一条简单的记录(DB 表是用字符串作为键的,因为每个字符串都是方法的名称,所以我只想要表中的每个行),其余行是一系列时间戳告诉我事情发生的时间。
  3. 如果找不到记录,则返回异常,因为无能为力。
  4. 如果您找到该记录,请查看第二个日期(如果它完全丢失),然后设置为 true,因为这是第一次运行。
  5. 如果第一个日期大于第二个日期,则最后还是要开始实际操作,因为它已更新,是时候运行了。否则,如果没有,请设置为 False,因为还没有更新。

所以这里是代码......我正在尝试做的是将其缩减为运行这些检查的最佳和最快的方法。我不关心数据库连接问题或类似问题。

    private static bool isLastIntervalNewerThanDB(string muiMethod)
    {
       using (var db = new IntLMPDB())
        {
            // Try to load a matching record.
            LastIntervalUpdated liRec = db.LastIntervalUpdateds.FirstOrDefault(rec => rec.method == muiMethod);
            // If it could not be loaded, exit because there's no way to determine if we should run.
             if (liRec == null) { throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); }
            else
            {
                // we have a valid interval record, so lets check that it has been updated since the last webPostTime.
                // put another way, there are three datetime values in the LastIntervalUpdated table. First is the
                // interval itself, second is the retrievalTime and third is the webPostTime. Whenever the MUI is 
                // checked for a new interval if one is found then the code updates the retrievalTime to the current
                // instant in time. This tells us what the last interval this application found on its last run was.
                // The thrid value is the webPostTime, this time instant is only updated by this very method we're in
                // right here. We can use this logic: if the retrievalTime is greater than the webPostTime then there's
                // a newer interval that we haven't yet processed and inserted into the databse. So we should run the
                // method below and update ALL of the syncable values into the databse. Then we'll set the dbPostTime to 
                // the current instance. As it goes, if this program then runs again before the interval is updated
                // then the dbPostTime will be greater than the retrieval time and we'll know to do nothig. Simple Right? :)

                // or check here includes a NULL check on dbPostTime because it's possible that dbPostTime is NULL,
                // in the example of the first time the system runs. It might have run a LastUpdate sync and not yet
                // done this method, so dbPostTime would be NULL. None of the other columns are allowed to be null.
                if (liRec.dbPostTime_EST == null || liRec.retrievalTime_EST > liRec.dbPostTime_EST)
                { return true; }
                else { return false; }
            }
       }
    }

【问题讨论】:

  • 像这样的过多代码 cmets 比帮助 imo 更伤害 - 在大多数情况下,代码应该说明一切,或者最多可能需要 3 行解释,别忘了你必须同时维护代码 cmets 以使其保持最新状态。
  • 是的,代码注释后面需要一个“TL;DR”。

标签: c# if-statement


【解决方案1】:

我认为逻辑很好。我建议你做这样的事情来提高可读性*:

private static bool isLastIntervalNewerThanDB(string muiMethod)
{
   using (var db = new IntLMPDB())
    {
        LastIntervalUpdated liRec 
            = db.LastIntervalUpdateds
                    .FirstOrDefault(rec => rec.method == muiMethod);

        if (liRec == null) 
        { 
            throw new Exception(
                string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); 
        }

        return liRec.dbPostTime_EST == null 
            || liRec.retrievalTime_EST > liRec.dbPostTime_EST;        
   }
}

*虽然可读性是主观的,但我认为if (liRec == null) 之后的else 只会添加不必要的嵌套,并且最终的条件可以折叠成单个表达式。也永远不要低估长表达式中放置良好的换行符 - 它可以在可读和不可读代码之间产生所有差异。

【讨论】:

  • 由于我基本上复制粘贴你的答案没有意义,我还建议对 IsNullOrEmpty 进行检查 muiMethod 。授予代码当前的方式,它仍然会达到第二个 if 块,但它可以节省为 db 分配空间(我知道这是通过 using 块处理的)
  • 同意 100% RE:在第一个 if 之后省略 else。
【解决方案2】:
private static bool isLastIntervalNewerThanDB(string muiMethod)
    {
       using (var db = new IntLMPDB())
        {
            // Try to load a matching record.
            LastIntervalUpdated liRec = db.LastIntervalUpdateds.FirstOrDefault(rec => rec.method == muiMethod);
            // If it could not be loaded, exit because there's no way to determine if we should run.
             if (liRec == null) { 
                     throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); 
             }

                // we have a valid interval record, so lets check that it has been updated since the last webPostTime.
                // put another way, there are three datetime values in the LastIntervalUpdated table. First is the
                // interval itself, second is the retrievalTime and third is the webPostTime. Whenever the MUI is 
                // checked for a new interval if one is found then the code updates the retrievalTime to the current
                // instant in time. This tells us what the last interval this application found on its last run was.
                // The thrid value is the webPostTime, this time instant is only updated by this very method we're in
                // right here. We can use this logic: if the retrievalTime is greater than the webPostTime then there's
                // a newer interval that we haven't yet processed and inserted into the databse. So we should run the
                // method below and update ALL of the syncable values into the databse. Then we'll set the dbPostTime to 
                // the current instance. As it goes, if this program then runs again before the interval is updated
                // then the dbPostTime will be greater than the retrieval time and we'll know to do nothig. Simple Right? :)

                // or check here includes a NULL check on dbPostTime because it's possible that dbPostTime is NULL,
                // in the example of the first time the system runs. It might have run a LastUpdate sync and not yet
                // done this method, so dbPostTime would be NULL. None of the other columns are allowed to be null.

               return liRec.dbPostTime_EST == null 
                      || liRec.retrievalTime_EST > liRec.dbPostTime_EST;     

       }
    }

【讨论】:

    【解决方案3】:

    保留第一个 if 去掉第一个 else 并将最后一个压缩成一行 if/else

    if (liRec == null) { throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod)); }
    
    liRec.dbPostTime_EST == null || liRec.retrievalTime_EST > liRec.dbPostTime_EST ? return true : return false
    

    【讨论】:

    • 你的第二行不会编译 - 无论如何都会很糟糕,当你可以做 return liRec.dbPostTime_EST == null || liRec.retrievalTime_EST > liRec.dbPostTime_EST;
    • 像这样使用条件运算符是 JavaScript 主义。如果它在 C# 中工作会很酷,但不幸的是它没有。 :)
    • 我意识到这个表达式有太多条件无法正确计算:\
    【解决方案4】:

    我会将布尔逻辑移至 LastIntervalUpdated 类:

    public class LastIntervalUpdated
    {
        public bool IsLastIntervalNewer
        {
            get
            {
                return this.dbPostTime_EST == null || this.retrievalTime_EST > this.dbPostTime_EST
            }
        }
        //other properties...
    }
    

    然后你可以把注释放在更接近定义的地方。它还允许您将查询简化为:

    private static bool isLastIntervalNewerThanDB(string muiMethod)
    {
        using (var db = new IntLMPDB())
        {
            LastIntervalUpdated liRec = db.LastIntervalUpdateds.FirstOrDefault(rec => rec.method == muiMethod);
            if(liRec == null) throw new Exception(string.Format("Could NOT find LastIntervalUpdated record for muiMethod: {0}", muiMethod))
            return liRec.IsLastIntervalNewer;
        }
    }
    

    我还会考虑为失败的查找创建异常类型,例如 ObjectNotFoundException,而不是直接抛出 Exception。

    【讨论】:

      猜你喜欢
      • 2011-01-14
      • 2010-10-07
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      相关资源
      最近更新 更多