.net 声明的委托上出现编译错误“无法转换”

u7up0aaq  于 2023-01-14  发布在  .NET
关注(0)|答案(3)|浏览(161)

我在LINQ中将委托作为Where参数传递时遇到了问题。
我在命名空间中声明一个委托:
public delegate bool FilterInt<in T>(T x);
我创建了一个方法来赋值给委托,然后再赋值给它:

public static bool FilterData(int val)
    {
        if (val < 10)
            return true;
        return false;

    }

当我尝试使用委托筛选List时,收到编译时错误“无法从FilterInt转换到Func〈Int,bool〉:

listInt.Where(_filterer);

但是,我可以使用下面的(一个隐含的委托?)没有任何问题:

listInt.Where(FilterData);

当我按照MSDN文档中关于delegates here的说明在名称空间中定义自己的delegate时,我遇到了与_comparer相同的问题:

public delegate int Comparison<in T>(T x, T y);

public static int CompareLength(string left, string right) =>
     right.Length.CompareTo(left.Length);

readonly Comparison<string> _comparer = CompareLength;

list.Sort(_comparer);

但是,如果我省略Comparison的初始声明,它就可以正常工作(注意- Comparison存在于System名称空间中)。
我想这是我最初的委托声明的问题。

j8ag8udp

j8ag8udp1#

Enumerable.Where接受Func<TSource, bool>委托。如果您查找有关Func<T,TResult>的文档,您会发现它声明为:

public delegate TResult Func<in T,out TResult>(T arg);

因此,您需要将委托“转换”为Func<TSource, bool>的示例,这可以通过直接创建委托的示例来实现:

new[] { 1 }.Where(new Func<int, bool>(_filterer));

或者使用匿名(lambda)函数:

new[] { 1 }.Where(i => _filterer(i));

它实际上是一种语法糖,被编译器转换成如下形式:

// generated class to hold your lambda:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
    public FilterInt<int> _filterer;
    // your lambda: 
    internal bool <M>b__0(int i)
    {
        return _filterer(i);
    }
}

   
// instantiation of new Func<int, bool>
Enumerable.Where(array, new Func<int, bool>(<>c__DisplayClass0_.<M>b__0));

方法组调用(listInt.Where(FilterData);)也是编译器扩展到创建新委托的语法糖:

Enumerable.Where(array, new Func<int, bool>(FilterData));
g2ieeal7

g2ieeal72#

你可以这样打电话。

Where(new Func<int, bool>(FilterInt))

或者

.Where(x => FilterInt(x))
dpiehjr4

dpiehjr43#

发生错误的原因是where子句需要一个布尔值为TResultFunc<TSource, TResult>,而不仅仅是一个Func<int>作为其代表。

IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)

如您所愿使用它的最接近的方式是这样的,但我不认为它是一个好的实现。

using System;
using System.Collections.Generic;
using System.Linq;

public delegate Func<T1, T2> FilterInt<in T1, out T2>(T1 value);

namespace DelegateTest
{
    class Program
    {
        private static readonly List<int> List = new List<int> {0, 1, 2, 10, 11, 12};

        static void Main(string[] args)
        {
            FilterInt<int, bool> filterInt = FilterData;
            var result = List.Where(x => filterInt.Invoke(x).Invoke(x));
            foreach (var item in result) Console.WriteLine(item.ToString());
        }

        private static Func<int, bool> FilterData(int value) => _ => value < 10;
    }
}

相关问题