期望的方法名称 - 使用lambda表达式错误?

时间:2015-09-26 23:51:00

标签: c# lambda

我正在自定义集合中实现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

4 个答案:

答案 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。无需推出自己的产品。