我正在自定义集合中实现Contains(T item)
方法。
以下工作(因为它基本上是Microsoft的实现的副本):
public class aCollection:IEnumerable<T>
{
T[] items;
public int Count{ get; private set;}
//...
public bool Contains(T item)
{
EqualityComparer<T> defaultComparer = EqualityComparer<T>.Default;
for (int i = 0; i < Count; i++)
if (defaultComparer.Equals(items[i], item))
return true;
return false;
}
}
然而,在使用此解决方案时,我尝试了另一种方法,但我无法理解构建因Method name expected
错误而失败的确切原因:
public class aCollection:IEnumerable<T>
{
T[] items;
public int Count{ get; private set;}
//...
public bool Contains(T item)
{
for (int i = 0; i < Count; i++)
if ((x => x == item)(items[i])) //Method name expected
return true;
return false;
}
}
我在使用lambdas时误解了什么?是因为某种原因我不能使用它们,或者我只是写错了表达式?
编辑:我希望函数做的是检查我的集合,找出它是否包含参数。 for循环中的行应该逐个地将T[] items
中的现有元素与传递的T item
进行比较,直到找到匹配并返回true
。或者,如果在整个数组中找不到匹配项,只需返回false
。
提前致谢,
hlfrmn
答案 0 :(得分:2)
应将Lambda表达式转换为要使用的委托。以下代码看起来很奇怪,但lambda没有编译错误:
public bool Contains(T item)
{
for (int i = 0; i < Count; i++)
if (((Func<T, bool>)((T x) => x == item))(items[i]))
return true;
return false;
}
为避免在每次迭代时创建新委托,可以在循环之前存储它:
public bool Contains(T item)
{
Func<T, bool> comparer = (T x) => x == item;
for (int i = 0; i < Count; i++)
if (comparer(items[i]))
return true;
return false;
}
但它仍然存在一个重要问题:运算符==
未定义泛型类型(如C ++)。我建议使用EqualityComparer<T>.Default
来比较值。
答案 1 :(得分:1)
而不是像这样使用它:
for (int i = 0; i < Count; i++)
if ((x => x == item)(items[i]))
return true;
只需使用Any
LINQ方法并传递lambda表达式,如下所示:
if (items.Any(x => x == item))
return true;
如果由于某种原因需要将lambda表达式用作函数(这似乎是你想要做的),那么你可以这样做:
Expression<Func<T,bool>> lambda_expression = (x => x == item);
Func<T, bool> function = lambda_expression.Compile();
for (int i = 0; i < Count; i++)
{
if (function(items[i]))
return true;
}
答案 2 :(得分:1)
如果您想采用自己的方法,请将代码更改为
public bool Contains(T item)
{
for (int i = 0; i < Count; i++)
if (items[i].Equals(item))
return true;
return false;
}
这里你明确地迭代了集合,所以不需要使用lambda。当你写这篇文章时
if ((x => x == item)(items[i]))
- 编译器不理解x
指的是什么!
如果你想使用lambda,你可以用更优雅的方式写作,比如
public bool Contains(T item)
{
return items.Any(i => i.Equals(item));
}
注意:使用EquityComparer
默认值,例如MSDN示例,否则您将错过EqualityComparer
类型可能已实施的任何T
。请参阅this以了解`EquityComparer.Default。
<强>更新强>
如果您看到 CLR core libraries
,则 .Any()
的实施方式
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
foreach (TSource element in source)
{
if (predicate(element)) return true;
}
return false;
}
因此,从实际实现中,您可以看到它完全符合您的要求。您可以在此GitHub Repo中查看其他 Linq Enumerable Extensions
,并探索其他标准Linq方法的实现。
答案 3 :(得分:-1)
实际上,更好的解决方案是 不 来实现您自己的Contains()
方法。
由于您的自定义集合实现了IEnumerable<T>
,因此它意味着您可以免费获得所有IEnumerable<T>
LINQ扩展方法,包括Enumerable.Contains<TSource> Method。无需推出自己的产品。