Linq中的多个where或条件指向对象

本文关键字:条件 对象 where Linq | 更新日期: 2023-09-27 18:12:13

我有一个TelephoneDataType对象列表

 public List<TelephoneDataType> Values { get; set; }

TelephoneDataType对象有一个名为ChartType的枚举属性

public class TelephoneDataType
{
  public ChartType ChartId { get; set; }
}

因此,从这个值列表中,我想取出所有ChartId设置为以下值的TelephoneDataType对象:

回答被遗弃的ExpectedWaitInQueue

这是我失败的尝试

var items = telephoneData.Values
                    .Where(c => c.ChartId == Enums.ChartType.Answered)
                    .Where(c => c.ChartId == Enums.ChartType.Abandoned)
                    .Where(c => c.ChartId == Enums.ChartType.ExpectedWait)
                    .Where(c => c.ChartId == Enums.ChartType.InQueue).ToArray();

Linq中的多个where或条件指向对象

你目前的解决方案是在你的.Where条款之间做&&。您需要通过执行以下操作之一使它们成为||

var items = telephoneData.Values
                         .Where(c => c.ChartId == Enums.ChartType.Answered
                                  || c.ChartId == Enums.ChartType.Abandoned
                                  || c.ChartId == Enums.ChartType.ExpectedWait
                                  || c.ChartId == Enums.ChartType.InQueue
                               )
                         .ToArray();

或者

(更容易读,更容易更新/维护)
  var myFilterList = new [] 
  {
      Enums.ChartType.Answered,
      Enums.ChartType.Abandoned,
      Enums.ChartType.ExpectedWait,
      Enums.ChartType.InQueue
  };
   var items = telephoneData.Values
                            .Where(c => myFilterList.Contains(c.ChartId)
                            .ToArray();

还要记住,您的.Where子句不会立即执行。
它们只在执行.ToList.ToArray等操作时执行。你可以在这里了解更多:https://msdn.microsoft.com/en-us/library/vstudio/bb738633(v=vs.100).aspx

我宁愿为Enums.ChartType实现扩展方法,例如

  public static class EnumsChartTypeExtensions {
    //TODO: find out a proper name for the method
    public static Boolean IsOnLine(this Enums.ChartType value) { 
      return value == Enums.ChartType.Answered || 
             value == Enums.ChartType.Abandoned ||
             value == Enums.ChartType.ExpectedWait ||
             value == Enums.ChartType.InQueue; 
    }
  }

那么你的Linq将会更容易读:

  var items = telephoneData.Values
    .Where(c => c.ChartId.IsOnLine())
    .ToArray();
该解决方案的另一个优点是,如果你在Enums.ChartType(例如WaitingForAnswer)中添加一些状态,你所要做的就是只更新扩展方法(而不是整个应用程序中的所有Linq)

一步一步地思考你的查询。首先,您将获得ID为Answered的所有图表。然后将该列表过滤为Abandoned,但是条目都已经是Answered了。

尝试使用or操作符。

var items = telephoneData.Values
                .Where(c => c.ChartId == Enums.ChartType.Answered ||
                            c.ChartId == Enums.ChartType.Abandoned ||
                            c.ChartId == Enums.ChartType.ExpectedWait ||
                            c.ChartId == Enums.ChartType.InQueue).ToArray();

每个Where返回一个过滤的可枚举对象,因此在您的第一个Where之后,您只剩下一个ChartType。您必须将这些条件组合成一个Where操作,如下所示:

var items = (telephoneData.Values
                    .Where(c => c.ChartId == Enums.ChartType.Answered || c.ChartId == Enums.ChartType.Abandoned || c.ChartId == Enums.ChartType.ExpectedWait || c.ChartId == Enums.ChartType.InQueue)
                    .ToArray());

我认为最好的方法是为枚举编写一个特殊的扩展方法,这不仅可以帮助您处理这种情况:

 public static class EnumExtensions
 {
        public static bool InSet<T>(this T target, params T[] possibleValues) where T : struct 
        {
            return possibleValues.Contains(target);
        }
    }

解为:

var items = telephoneData.Values
                .Where(c => c.ChartId.InSet(Enums.ChartType.Answered, 
                                            Enums.ChartType.Abandoned,
                                            etc...);