我有List<T>
个User
个实例,我需要搜索User
中的所有字段。
最有效的方法是什么?
这是我的User
类的定义:
public class User
{
public String SamAccountName { get; set; }
public String EmailAddress { get; set; }
public String WorkPhone { get; set; }
public String MobilePhone { get; set; }
public String Office { get; set; }
}
我需要搜索以查看“Tom”的值是否包含在任何字段的任何字符串中,并返回一个只有符合该条件的实例的新List<T>
。
我想用LINQ做这个,但不知道怎么做。我怎么能这样做?
答案 0 :(得分:5)
假设你有一个IEnumerable<User>
,你可以这样做:
// Query for "Tom" being contained in any of the fields.
var query =
from user in users
where
(user.SamAccountName != null && user.SamAccountName.Contains("Tom")) ||
(user.EmailAddress != null && user.EmailAddress.Contains("Tom")) ||
(user.WorkPhone != null && user.WorkPhone.Contains("Tom")) ||
(user.MobilePhone != null && user.MobilePhone.Contains("Tom")) ||
(user.Office != null && user.Office.Contains("Tom"))
select user;
注意,如果任何这些字段为空,则null
的检查很重要,否则,当您在Contains
method上调用String
class时,它会抛出{{} 3}}因为没有字符串可以调用Contains
。
NullReferenceException
只是映射到where
clause上的Where
extension method(请确保有using System.Linq;
声明,以便编译器识别扩展方法。)
如果您认为空检查过多和/或重复,您可以像这样减少代码:
// Generate your predicate.
Func<string, bool> checkContainsTom = s => s != null && s.Contains("Tom");
// Query.
var query =
from user in users
where
checkContainsTom(user.SamAccountName) ||
checkContainsTom(user.EmailAddress) ||
checkContainsTom(user.WorkPhone) ||
checkContainsTom(user.MobilePhone) ||
checkContainsTom(user.Office)
select user;
这稍微好一些,因为你正在封装冗余逻辑;如果逻辑发生变化,您只需在一个地方更改它,它就会应用于所有检查。如果需要,可以随意使用函数替换Enumerable
class。
如果您想使用lambda expression,则可以使用foreach
通过query
进行枚举。如果您在实体列表中需要它(例如deferred execution),那么您只需调用Enumerable
类上的List<User>
,就像这样:
IList<User> materializedResults = query.ToList();
答案 1 :(得分:3)
它不漂亮,但应该有效:
users.Where(u => u.SamAccountName.Contains("Tom") ||
u.EmaildAddress.Contains("Tom") ||
u.WorkPhone.Contains("Tom") ||
u.MobilePhone.Contains("Tom") ||
u.Office.Contains("Tom"));
虽然,我不得不说,我不明白为什么你需要在电话号码里搜索字符串“Tom”。
答案 2 :(得分:3)
在一些静态类中复制一个通用扩展方法:
public static IEnumerable<T> WhereAtLeastOneProperty<T, PropertyType>(this IEnumerable<T> source, Predicate<PropertyType> predicate)
{
var properties = typeof(T).GetProperties().Where(prop => prop.CanRead && prop.PropertyType == typeof(PropertyType)).ToArray();
return source.Where(item => properties.Any(prop => PropertySatisfiesPredicate(predicate, item, prop)));
}
private static bool PropertySatisfiesPredicate<T, PropertyType>(Predicate<PropertyType> predicate, T item, System.Reflection.PropertyInfo prop)
{
try
{
return predicate((PropertyType)prop.GetValue(item));
}
catch
{
return false;
}
}
然后你打电话:
var usersList = new List<User>();
var filteredUsersList = usersList.WhereAtLeastOneProperty((string s) => s.Contains("Tom")).ToList();
或者使用其他一些lambda来更好地满足您的需求。 e.g。
.WhereAtLeastOneProperty((string s) => s=="Tom")