【问题标题】:How to replace IF statements for dictionary? (C#, Linq)如何替换字典的 IF 语句? (C#,Linq)
【发布时间】:2020-11-19 05:28:20
【问题描述】:

我有一个 SampleObject 的相等比较器:

    public bool Equals(SampleObject x, SampleObject y)
    {
        if (x == null)
        {
            return y == null;
        }

        if (y == null)
        {
            return false;
        }

        if (!string.Equals(x.SomeId, y.SomeId))
        {
            return false;
        }

        if (x.EventsList == null)
        {
            return y.EventsList == null;
        }

        if (y.EventsList == null)
        {
            return false;
        }

        return x.EventsList.OrderBy(e => e)
            .SequenceEqual(y.EventsList.OrderBy(e => e));
    }

我想知道是否有办法替换字典中的所有 IF 子句?

【问题讨论】:

  • 不是答案,而是观察:当 x.EventsList 和 y.EventsList 都为空时,您将它们视为相等 - 但当 x 和 y 都为空时,您将它们视为不相等。你是故意的吗?
  • @MatthewWatson:我不这么认为:如果 x 和 y 都为 null,则 if (x == null) return y == null 将返回 true。莱蒂没有改变问题,不是吗?
  • 你确定是指字典吗?它的关键/价值是什么?或者你是否在使用某种机制,你有某种可枚举的规则集,而第一个返回的规则会终止规则的枚举?
  • 旁注:请避免null 用于集合,例如EventList;改用空的
  • @GWimpassinger Doh。 :) 当然你是对的。我需要增加我的字体大小...

标签: c# .net linq dictionary if-statement


【解决方案1】:

这是不可能的字典,但有一个列表。字典没有顺序,因此您不能保证您的检查以正确的顺序执行。我使用了一个元组列表,其中第一项是条件,第二项是返回值。您的代码如下:

public bool Equals(SampleObject x, SampleObject y)
{
var checks = new List<(Func<bool>,Func<bool>)>
{
    (() => x == null, () => y == null),
    (() => y == null, () => false),
    (() => !string.Equals(x.SomeId, y.SomeId), () => false),
    (() => x.EventsList == null, () => y.EventsList == null),
    (() => y.EventsList == null, () => false)
};
foreach(var entry in checks)
{
     if(entry.Item1.Invoke())
     {
       return entry.Item2.Invoke();
     }
}
return x.EventsList.OrderBy(e => e)
            .SequenceEqual(y.EventsList.OrderBy(e => e));
}

但我强烈建议保留您的原始版本,因为从我的角度来看,这种方法的可读性会大大降低。有时,一个经典的 if 语句序列比任何花哨的 LINQ 或其他任何东西都更合适。

【讨论】:

  • 我会将其设置为正确答案,因为它确实提供了“调度”解决方案的选项。但我认为,正如@SomeBody 所建议的那样,我会尝试使用更简单的描述方式。
【解决方案2】:

好吧,我怀疑Dictionary 在这里是否有任何帮助,但是您可以将例程稍微简化为

public bool Equals(SampleObject x, SampleObject y) {
  if (ReferenceEquals(x, y))
    return true;
  else if (x == null || y == null)
    return false;

  // From now on, both x and y are not null

  //TODO: to avoid such constructions, do not let collections be null, but empty 
  if (x.EventList == null || y.EventList == null)
    return x.EventList == y.EventList;

  // From now on, both x.EventList and y.EventList are not null

  return string.Equals(x.SomeId, y.SomeId) &&
         x.EventList.OrderBy(e => e).SequenceEquals(y.EventList.OrderBy(e => e));
}

【讨论】:

  • 我喜欢这个!看起来很干净,而且不那么重复。
【解决方案3】:

我认为字典在这里没有任何帮助。您可以用一个简单的表达式替换所有 if 语句:

return
    x == null && y == null ||
    x != null && y != null &&
    String.Equals(x.SomeId, y.SomeId) &&
    (x.EventsList == null && y.EventsList == null ||
     x.EventsList != null && y.EventsList != null &&
     x.EventsList.OrderBy(e => e)
        .SequenceEqual(y.EventsList.OrderBy(e => e));

请注意,由于 C# 的 short-circuit evaluation,在大多数情况下只需要对表达式进行部分计算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    相关资源
    最近更新 更多