方法名称预期-使用lambda表达式错误

本文关键字:使用 lambda 表达式 错误 方法 | 更新日期: 2023-09-27 18:14:53

我正在自定义集合中实现Contains(T item)方法。下面的工作(因为它基本上是微软实现的副本):

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

方法名称预期-使用lambda表达式错误

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来比较值

不像这样使用:

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;
}

如果您想使用您的方法,请将代码更改为

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的例子一样,否则你会错过T类型可能实现的任何EqualityComparer

如果你看到 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方法的实现。

实际上,更好的解决方案是而不是来实现您自己的Contains()方法。

既然您的自定义集合实现了IEnumerable<T>,那么这意味着您可以免费获得所有IEnumerable<T> LINQ扩展方法,包括Enumerable.Contains方法。不需要推出自己的

相关文章: