【问题标题】:How to write this sentinel loop having a null check in a cleaner, shorter and efficient way?如何以一种更简洁、更短、更高效的方式编写具有空值检查的哨兵循环?
【发布时间】:2021-05-01 02:05:12
【问题描述】:

我使用null 作为哨兵/行程值来突破 foreach:

public static DataTable ExecuteQuery(string sql)
{
    var conn = new SqlConnection(EnvironmentVariables.GetDbConnectionString());
    var adapter = new SqlDataAdapter(sql, conn);
    var table = new DataTable();
    adapter.Fill(table);
    return table;
}
private VacantSummaryPage SelectPropertyFromDb(string sql)
{
    VacantProperty vacantProperty = null;
    List<VacantProperty> vacantProperties = GetProperties();
    foreach (DataRow row in SqlServer.ExecuteQuery(sql).Rows)
    {
        vacantProperty = vacantProperties.Find(v => v.GetTitle().Contains(row["PartialStreetAddress"].ToString()));
        if (vacantProperty != null) break;
    }
    vacantProperty.Select();
    return new VacantSummaryPage(driver);
}

它的作用是,一旦 vacantProperty 匹配到它不再为空的位置,就跳出循环并 Select() 该属性。

【问题讨论】:

  • 似乎您想Select() 第一个符合给定条件的项目。看起来很适合 First() docs.microsoft.com/en-us/dotnet/api/…
  • @CodeCaster 只是在探索其他方式。我不能问我不知道的事情,所以希望更有经验的开发人员能伸出援助之手。很高兴知道当前代码做了它应该做的事情,而您的回答实际上是一个客观的答案。最近,在 SO 中提问感觉就像把手伸进狮子的笼子里一样。 :)
  • @OlivierRogier 哈哈我也找到了! :) 非常感谢,它成功了!如果有人需要,我在原始帖子中添加了您的解决方案。如果此线程被重新打开,请再次发布,我将投票并接受。我给你这个模因作为我的感谢 - devhumor.com/media/thank-you-guys-you-are-the-real-heroes
  • @silver 没那么错,但不是真的。这是量子...
  • @OlivierRogier 今天我还学到的是 LINQ 理解查询。感谢您展示示例。

标签: c# loops refactoring sentinel null-check


【解决方案1】:

您可以使用 LINQ 理解查询(类似 SQL 的语法)编写“单行”指令:

private VacantSummaryPage SelectPropertyFromDb(string sql)
{
  var query = from row in SqlServer.ExecuteQuery(sql).Rows.Cast<DataRow>()
              from property in GetProperties()
              where property.GetTitle().Contains(row["PartialStreetAddress"].ToString())
              select property;
  vacantProperty = query.FirstOrDefault();
  if ( vacantProperty != null )
    vacantProperty.Select();
  return new VacantSummaryPage(driver);
}

仅使用First 将在未找到时引发异常,因此使用FirstOrDefault 我们可以控制未找到的情况,除非首选异常控制。

这里查询本身被延迟,例如在调用 First/FirstOrDefault 或 ToList() 时对其进行评估。

LINQ deferred (or immediate?) execution

Deferred Execution of LINQ Query

LINQ: Why is it called "Comprehension Syntax"

Query Syntax and Method Syntax in LINQ (C#)

LINQ Query Syntax (Comprehensive)

LINQ Method Syntax (Lambda)

很高兴知道

DataSet 使用的TypedTableBase 允许直接实现IEnumerable&lt;DataRow&gt;Typed DataSets

【讨论】:

  • 你才是真正的mvp!将看看那些文档:))
  • 你能解释一下这如何更干净、更短或更高效吗?
  • @CodeCaster 与原始代码相比?没有循环。没有如果。没有中断(在使用 for/foreach 的情况下)。该循环由单个 Linq 查询替换。总计:六行而不是九行(我不计算添加的空检查测试,或者如果在选择之后调用 First 则为 5 行,但我估计可读性较差)。易于阅读和理解。你想要更多的理由吗?我认为更直观。更好的可维护性。与时俱进。相比 lambda,我更喜欢理解语法,但 lambda 也很酷,可以更短更强大,但反之亦然,这取决于具体情况。
猜你喜欢
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多