在对象 C# 列表中搜索属性



有一个人员和搜索对象列表。搜索对象是在主列表上进行搜索。

public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public int Zip { get; set; }
public string OtherDetails { get; set; }
}
public class SearchParam
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? DOB { get; set; }
}

我正在使用SearchParam对象来搜索List<Person>. 我的搜索功能如下所示:

List<Person> GetResult(SearchParam search, List<Person> persons)
{
if (search == null && persons == null)
{
if (!string.IsNullOrWhiteSpace(search.FirstName)
&& string.IsNullOrWhiteSpace(search.LastName)
&& !search.DOB.HasValue
)
{
return persons.Where(p => p.FirstName.ToUpper().StartsWith(search.FirstName.ToUpper())).ToList();
}
if (string.IsNullOrWhiteSpace(search.FirstName)
&& !string.IsNullOrWhiteSpace(search.LastName)
&& !search.DOB.HasValue
)
{
return persons.Where(p => p.LastName.ToUpper().StartsWith(search.LastName.ToUpper())).ToList();
}
if (string.IsNullOrWhiteSpace(search.FirstName)
&& string.IsNullOrWhiteSpace(search.LastName)
&& search.DOB.HasValue
)
{
return persons.Where(p => p.DOB.Equals(search.DOB)).ToList();
}
if (!string.IsNullOrWhiteSpace(search.FirstName)
&& !string.IsNullOrWhiteSpace(search.LastName)
&& !search.DOB.HasValue
)
{
return persons.Where(p => p.FirstName.ToUpper().StartsWith(search.FirstName.ToUpper())
&& p.LastName.ToUpper().StartsWith(search.LastName.ToUpper())).ToList();
}
if (!string.IsNullOrWhiteSpace(search.FirstName)
&& !string.IsNullOrWhiteSpace(search.LastName)
&& search.DOB.HasValue
)
{
return persons.Where(p => p.FirstName.ToUpper().StartsWith(search.FirstName.ToUpper())
&& p.LastName.ToUpper().StartsWith(search.LastName.ToUpper())
&& p.DOB.Equals(search.DOB)).ToList();
}
return persons;
}
else
{
return persons;
}
}

这段代码"GetResult"正在工作,但我对此不满意。 我应该如何处理列表和搜索对象中的空值并最小化此方法中的代码行数?

使用 Linqs 流水线

var workingList = persons;
if(searchParam.FirstName != null)
workingList = workingList.Where(p=>p.FirstName.Startswith(searchParam.FirstName));
if(searchParam.LastName != null)
workingList = workingList.Where(p=>p.LAstName.StartsWith(searchParam.LastName));
etc.

最后

return workingList.ToList();

即一次组装一个过滤器,然后在最后进行枚举

我建议一种return较少的方法。

这是我的尝试:

/// <summary>
/// Returns a filtered list of persons
/// </summary>
/// <param name="search">Filters. Only filters that are set (not null or empty) are applied</param>
/// <param name="persons">List to filter</param>
/// <returns>Filtered list or a new list of all persons if no filters provided</returns>
/// <exception cref="ArgumentNullException"> Thrown if 'search' or 'persons' is null </exception>
static List<Person> Filter(SearchParam search, IEnumerable<Person> persons)
{
if( search == null ) throw new ArgumentNullException(nameof(search));
if (persons == null) throw new ArgumentNullException(nameof(persons));
IEnumerable<Person> filtered = persons;
if( !string.IsNullOrEmpty(search.FirstName))
{
filtered = filtered.Where( p => string.Compare( p.FirstName, search.FirstName, StringComparison.CurrentCultureIgnoreCase ) == 0);
}
if (!string.IsNullOrEmpty(search.LastName))
{
filtered = filtered.Where(p => string.Compare(p.LastName, search.LastName, StringComparison.CurrentCultureIgnoreCase) == 0);
}
if (search.DOB.HasValue)
{
//This filter should probably allow searching only by year, etc.
filtered = filtered.Where(p =>p.DOB == search.DOB);
}
return filtered.ToList();
}

和例子

List<Person> l = new List<Person>();
l.Add(new Person
{
FirstName = "Prashant",
DOB = new DateTime(1990, 01, 02)
});
l.Add(new Person
{
FirstName = "TymTam",
LastName = "No Choc",
DOB = new DateTime(1977, 01, 02)
});
l.Add(new Person
{
FirstName = "Melissa",
LastName = "No Choc",
DOB = new DateTime(1977, 01, 02)
});
var filter = new SearchParam()
{
LastName = "No CHOC",
DOB = new DateTime(1977, 01, 02)
};
var filtered = Filter(filter, l);
foreach( var f in filtered)
{
Console.WriteLine($"{f.FirstName} {f.LastName} ({f.DOB})");
}

结果:

TymTam No Choc (2/01/1977 00:00:00)
Melissa No Choc (2/01/1977 00:00:00)

不要忘记单元测试!

您可以使用如下代码最小化if-else子句和嵌套块:

public static List<Person> GetResult(SearchParam search, List<Person> persons)
{
if (search == null || persons == null)
{
return persons;
}
var ignoreCase = StringComparison.CurrentCultureIgnoreCase;
var firstNamePrefix = string.IsNullOrWhiteSpace(search.FirstName) ? "" : search.FirstName;
var lastNamePrefix = string.IsNullOrWhiteSpace(search.LastName) ? "" : search.LastName;
return persons.Where(p => p.FirstName.StartsWith(firstNamePrefix, ignoreCase))
.Where(p => p.LastName.StartsWith(lastNamePrefix, ignoreCase))
.Where(p => p.DOB.Equals(search.DOB ?? p.DOB))
.ToList();
}

附言我冒昧地颠倒了你的第一个条件,即检查参数为空。

最新更新