我有以下全功能方法,它根据输入参数返回一个列表(如果没有找到有效的输入则返回所有内容):
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
List<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list
if ((dekorNr != null) && !dekorNr.Trim().Equals(String.Empty))
lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Artikelnummer.Contains(dekorNr));
if ((bezeichnung != null) && !bezeichnung.Trim().Equals(String.Empty))
lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Bezeichnung.Contains(bezeichnung));
if ((hersteller != null) && !hersteller.Trim().Equals(String.Empty))
lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Lieferant.Contains(hersteller));
return lstFoundPriceRows;
}
这三个参数可以是null
或String.Empty
,只应用于过滤源列表(如果它们不是null
或String.Empty
。
正如我所说,代码工作正常,但我对它不满意;)。这似乎太复杂了。有没有办法只创建一个优雅的动态linq语句?
答案 0 :(得分:2)
首先,您可以简化if条件:
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
List<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list
if (!string.IsNullOrWhitespace(dekorNr))
lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Artikelnummer.Contains(dekorNr));
if (!string.IsNullOrWhitespace(bezeichnung))
lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Bezeichnung.Contains(bezeichnung));
if (!string.IsNullOrWhitespace(hersteller))
lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Lieferant.Contains(hersteller));
return lstFoundPriceRows;
}
其次,您可以使用where子句,该子句实际上不会对列表执行扫描(您现在正在执行3次扫描):
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
IEnumerable<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list
if (!string.IsNullOrWhitespace(dekorNr))
lstFoundPriceRows = lstFoundPriceRows.Where(p => p.Artikelnummer.Contains(dekorNr));
if (!string.IsNullOrWhitespace(bezeichnung))
lstFoundPriceRows = lstFoundPriceRows.Where(p => p.Bezeichnung.Contains(bezeichnung));
if (!string.IsNullOrWhitespace(hersteller))
lstFoundPriceRows = lstFoundPriceRows.Where(p => p.Lieferant.Contains(hersteller));
return lstFoundPriceRows.ToList();
}
从现在开始你正在进行一次扫描,你可以在Where
谓词中移动条件:
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
IEnumerable<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list
lstFoundPriceRows = lstFoundPriceRows.Where(p => string.IsNullOrWhitespace(dekorNr) || p.Artikelnummer.Contains(dekorNr));
lstFoundPriceRows = lstFoundPriceRows.Where(p => string.IsNullOrWhitespace(bezeichnung) || p.Bezeichnung.Contains(bezeichnung));
lstFoundPriceRows = lstFoundPriceRows.Where(p => string.IsNullOrWhitespace(hersteller) || p.Lieferant.Contains(hersteller));
return lstFoundPriceRows.ToList();
}
由于您没有ifs,您可以将这些语句组合成一个。
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
return _lstABSPriceRows
.Where(p => string.IsNullOrWhitespace(dekorNr) || p.Artikelnummer.Contains(dekorNr))
.Where(p => string.IsNullOrWhitespace(bezeichnung) || p.Bezeichnung.Contains(bezeichnung))
.Where(p => string.IsNullOrWhitespace(hersteller) || p.Lieferant.Contains(hersteller))
.ToList();
}
最后,我们可以将所有Where
个谓词分组为一个(感谢@Kris):
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
return _lstABSPriceRows
.Where(p => (string.IsNullOrWhitespace(dekorNr) || p.Artikelnummer.Contains(dekorNr)) &&
(string.IsNullOrWhitespace(bezeichnung) || p.Bezeichnung.Contains(bezeichnung)) &&
(string.IsNullOrWhitespace(hersteller) || p.Lieferant.Contains(hersteller)))
.ToList();
}
您可以使用类似的扩展方法创建更简单(和3.5兼容)的IsNullOrWhitespace
:
public static bool IsNullOrWhitespace(this string s)
{
return (s == null || string.IsNullOrEmpty(s.Trim()));
}
随之而来的是表达变得更加简单:
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
return _lstABSPriceRows
.Where(p => (dekorNr.IsNullOrWhitespace() || p.Artikelnummer.Contains(dekorNr)) &&
(bezeichnung.IsNullOrWhitespace() || p.Bezeichnung.Contains(bezeichnung)) &&
(hersteller.IsNullOrWhitespace() || p.Lieferant.Contains(hersteller)))
.ToList();
}
答案 1 :(得分:0)
代码运行正常,但太复杂了。例如;如果您输入deKorNr和hersteller会发生什么?我不知道你是否可以用一个史诗般的linq语句解决这个问题并使其变得不那么复杂......
更好的解决方案是创建三个独立的函数,这些函数都有自己的逻辑。那么它首先不需要你原来的问题。
答案 2 :(得分:0)
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller)
{
List<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list
if (!string.IsNullOrWhitespace(dekorNr) || !string.IsNullOrWhitespace(bezeichnung)|| !string.IsNullOrWhitespace(hersteller) )
{
lstFoundPriceRows = lstFoundPriceRows.Where (p => p.Artikelnummer.Contains(dekorNr) ||
p.Bezeichnung.Contains(bezeichnung)||p.Lieferant.Contains(hersteller)).ToList();
}
else
{
// Your query without filters
}
}