我正在尝试创建一种优雅且可扩展的查询字典的方法,该字典将枚举映射到一组字符串。
所以我有这个类SearchFragments
,里面有字典。然后我想要一个方法,其中这个类的消费者可以简单地问“HasAny”,这是我正在努力的一点,只需传递一些查询,如表达式并获得布尔答案。
public class SearchFragments
{
private readonly IDictionary<SearchFragmentEnum, IEnumerable<string>> _fragments;
public SearchFragments()
{
_fragments = new Dictionary<SearchFragmentEnum, IEnumerable<string>>();
}
public bool HasAny(IEnumerable<SearchFragmentEnum> of)
{
int has = 0;
_fragments.ForEach(x => of.ForEach(y => has += x.Key == y ? 1 : 0));
return has >= 1;
}
}
目前的问题是,这个类的消费者现在必须构建一个可能非常混乱的IEnumerable<SearchFragmentEnum>
。
我正在寻找的是消费代码能够写下以下内容:
searchFragments.HasAny(SearchFragmentEnum.Name, SearchFragmentEnum.PhoneNumber)
但是这个参数列表的大小可能会有所不同(没有我必须在SearchFragments
类中为每个可能的组合编写方法重载(如果在将来将新值添加到SearchFragmentEnum
中约会我不必更新课程。
答案 0 :(得分:5)
您可以使用params[]
public bool HasAny(params SearchFragmentEnum[] of)
{ ...
旁注:您知道LIN(Q)查询应该只查询源并且不会引起任何副作用吗?但是您的查询会不必要地增加整数:
_fragments.ForEach(x => of.ForEach(y => has += x.Key == y ? 1 : 0));
而是使用它(也更有效,更可读):
return _fragments.Keys.Intersect(of).Any();
更有效的替代方案是Sergey's想法:
return of?.Any(_fragments.ContainsKey) == true;
答案 1 :(得分:3)
对于c#中可变大小的参数,请使用params
关键字:
public int HasAny(params SearchFragmentEnum [] of)
出于性能原因,.Net API通常会提供一些重载;传递的参数将复制到新数组中。明确地为最常见的情况提供重载可以避免这种情况。
public int HasAny(SearchfragmentEnum of1)
public int HasAny(SearchFragmentEnum of1, SearchFragmentEnum of2)
etc.
您也可以考虑使用[Flags]
属性标记枚举,而不是使用参数。参数可以像HasAny(SearchFragmentEnum.Name | SearchFragmentEnum.PhoneNumber
一样传递。 StackOverflow上丰富的示例(例如Using a bitmask in C#)
答案 2 :(得分:3)
使用params
关键字允许不同数量的参数。此外,您可以通过循环较小的of
数组来简化代码。此外,您正在使用具有O(1)密钥检查的字典,因此没有内部循环:
public bool HasAny(params SearchFragmentEnum[] of)
{
foreach(var o in of) {
if (this._fragments.ContainsKey(o))
return true;
}
return false;
}
或更短的LINQ
public bool HasAny(params SearchFragmentEnum[] of) {
return of?.Any(_fragments.ContainsKey) ?? false;
}