简体   繁体   English

ac#列表中的FindAll,但搜索词不同

[英]FindAll in a c# List, but varying search terms

    List<DTOeduevent> newList = new List<DTOeduevent>();
foreach (DTOeduevent e in eduList.FindAll(s => 
       s.EventClassID.Equals(cla) 
    && s.LocationID.Equals(loc)
    && s.EducatorID.Equals(edu))) 
       newList.Add(e);

cla, loc, edu can be (null or empty) or supplied with values-- cla,loc,edu可以为(null或为空)或提供值-

basically how can I simply return the original list (eduList) if cla, loc, edu are all null 基本上,如果cla,loc,edu全部为null,我如何简单地返回原始列表(eduList)

or search by loc, search by loc, edu, search by edu, cla -- etc........ 或按位置搜索,按位置搜索,edu,按edu搜索,cla等--........

my sample code only makes a new list if all 3 vars have values-- 我的示例代码仅在所有3个变量都具有值的情况下才创建新列表-

is there an elegant way to do this, without brute force if statements? 有没有一种优雅的方式来做到这一点,而无需强行使用if语句?

List<DTOeduevent> newList = eduList.FindAll(s => 
       (cla == null || s.EventClassID.Equals(cla))
    && (loc == null || s.LocationID.Equals(loc))
    && (edu == null || s.EducatorID.Equals(edu)));

Assuming the values are Nullable value types or classes. 假设值是可为空的值类型或类。 If they're strings, you could replace cla == null with String.IsNullOrEmpty(cla) . 如果它们是字符串,则可以用String.IsNullOrEmpty(cla)代替cla == null

IEnumerable<DTOeduevent> newList = eduList;
if (cla != null)
{
  newList = newList.Where(s => s.EventClassID == cla);
}
if (loc != null)
{
  newList = newList.Where(s => s.LocationID == loc);
}
if (edu != null)
{
  newList = newList.Where(s => s.EducatorID == edu);
}

newList = newList.ToList();

Due to deferred execution, the Where statements should all execute at once, when you call ToList ; 由于延迟执行,因此Where调用ToList时, Where语句应全部立即执行。 it will only do one loop through the original list. 它只会在原始列表中进行一个循环。

I would personally lean towards something that encapsulated the logic of what you seem to be doing here: checking that a found id is equal to some search id. 我个人倾向于采用某种封装您似乎在这里做的逻辑的东西:检查找到的ID是否等于某些搜索ID。 The only wrinkle is how to get that check for null or empty in there first. 唯一的麻烦是如何首先获取在那里是否为空或空的检查。

One way to do that is by using a static extension method: 一种方法是使用静态扩展方法:

public static class DtoFilterExtensions
{
    public static bool IsIdEqual(this string searchId, string foundId) {
        Debug.Assert(!string.IsNullOrEmpty(foundId));
        return !string.IsNullOrEmpty(searchId) && foundId.Equals(searchId);
    }

}

I would also lean towards using LINQ and IEnumerable<> as Domenic does, even though you could make it work with List.FindAll just as easily. 我也倾向于像Domenic一样使用LINQ和IEnumerable <>,即使您可以轻松地将它与List.FindAll一起使用也是如此。 Here would be a sample usage: 这将是一个示例用法:

    public void Filter(string cla, string loc, string edu) {
        var startList = new List<DTOeduevent>();
        var filteredList = startList
            .Where(x => x.classId.IsIdEqual(cla) && x.locationId.IsIdEqual(loc) && x.educatorId.IsIdEqual(edu));
        Show(filteredList.ToList());
    }

In your own code of course you have got that start list either in a member variable or a parameter, and this assumes you have got some method like Show() where you want to do something with the filtered results. 当然,在您自己的代码中,您可以在成员变量或参数中获得该开始列表,并且假定您有某种类似于Show()的方法要对过滤后的结果进行处理。 You trigger the deferred execution then, as Domenic explained with the ToList call (which is of course another extension method provided as part of LINQ). 然后,您触发延迟执行,如Domenic在ToList调用中所述(当然,这是LINQ的一部分提供的另一种扩展方法)。

HTH, HTH,
Berryl Berryl

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM