[英]Linq code refactoring
请帮助我使用Linq重构此代码。 如何只使用一次Where和ToList? 寻求帮助
private IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address,int? age)
{
var ans = new List<SomeClass>();
if (!String.IsNullOrEmpty(name))
ans = aaa.Where(x => x.name.equal(name)).ToList();
if (!String.IsNullOrEmpty(company))
ans = ans.Where(x => x.company.equal(company)).ToList();
if (!String.IsNullOrEmpty(address))
ans = ans.Where(x => x.address.equal(address)).ToList();
if (age.HasValue)
ans = ans.Where(x => x.age == age.Value).ToList();
return ans;
}
您可以使用此:
var ans = aaa.Where( x => ( string.IsNullOrEmpty(name)
|| x.name.equal(name)
)
&&
( string.IsNullOrEmpty(company)
|| x.company.equal(company)
)
&&
( string.IsNullOrEmpty(address)
|| x.address.equal(address)
)
&&
( !age.HasValue
|| x.age == age.Value
)
);
您可以放弃对ToList
所有呼叫。 没有这些调用,组合过滤将以您不需要关心的延迟方式执行。
如果您确实想影响执行过滤的时间(或确保结果基于调用Filter
时aaa
的快照,并且在以后更改aaa
不改变),请将最后一行更改为
return ans.ToArray();
(这里可能不需要列表;无论如何,返回值都键入IEnumerable<SomeClass>
,并且调用者不应期望能够直接修改(添加/删除项)返回的对象。
因此,完整的代码如下所示:
private IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address,int? age)
{
IEnumerable<SomeClass> ans = new SomeClass[0];
if (!String.IsNullOrEmpty(name))
ans = aaa.Where(x => x.name.Equals(name));
if (!String.IsNullOrEmpty(company))
ans = ans.Where(x => x.company.Equals(company));
if (!String.IsNullOrEmpty(address))
ans = ans.Where(x => x.address.Equals(address));
if (age.HasValue)
ans = ans.Where(x => x.age == age.Value);
return ans.ToArray();
}
正如其他答案所表明的那样,也可以将所有Where
调用合并到一个中,尽管坚持使用if
s和Where
s的原始链可以很清楚地显示出它的作用,这对于合并的解决方案可能并非如此。
只是在这里添加另一个答案。 为什么在所有输入中创建一个列表都是IEnumerable,所以输出是否相同?
private IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address, int? age)
{
if (!String.IsNullOrEmpty(name))
aaa = aaa.Where(x => x.name.Equals(name));
if (!String.IsNullOrEmpty(company))
aaa = aaa.Where(x => x.company.Equals(company));
if (!String.IsNullOrEmpty(address))
aaa = aaa.Where(x => x.address.Equals(address));
if (age.HasValue)
aaa = aaa.Where(x => x.age == age.Value);
return aaa;
}
我在这个问题上的两分钱:
Where
子句,因为如果您以这种方式保留它,则以后可以轻松添加新的过滤器参数,并且您的代码将易于阅读。 ToList()
。 String.IsNullOrEmpty()
考虑使用String.IsNullOrWhiteSpace()
这样,如果提供了非空但空白的字符串,则不会过滤掉实体。 x.name.Equals(name, StringComparison.InvariantCultureIgnoreCase)
考虑使用x.name.Equals(name, StringComparison.InvariantCultureIgnoreCase)
代替x.name.Equals(name)
。 您可以执行以下操作:
var ans = aaa.Where(x => !string.IsNullOrEmpty(name) ? x.name.equal(name) : false).ToList()
.Union(aaa.Where(x => !string.IsNullOrEmpty(company) ? x.company.equal(company) : false).ToList())
.Union(aaa.Where(x => !string.IsNullOrEmpty(address) ? x.address.equal(address) : false).ToList());
ans = ans.Where(x => age.HasValue ? x.age == age.Value : true).ToList();
您应该尝试这样的事情:
private static IEnumerable<SomeClass> Filter(IEnumerable<SomeClass> aaa, string name, string company, string address, int? age)
{
var ans = aaa.Where(x => !String.IsNullOrEmpty(name) ? x.Name.Equals(name) : true)
.Where(x => !String.IsNullOrEmpty(company) ? x.Company.Equals(company) : true
&& !String.IsNullOrEmpty(address) ? x.Address.Equals(address) : true
&& age.HasValue ? x.Age == age.Value : true);
return ans;
}
但是请注意,在您的代码中,如果“ name”参数为空,则始终返回0个结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.