c# - 无法将 lambda 表达式转换为委托类型;但这适用于列表功能
c# - Cannot convert lambda expression to delegate type; but this works in List functions
为什么当我在自定义方法的谓词参数中传递 lambda 表达式(即 p => p.Damage)时,定义如下:
public static void Sort(T[] input, int low, int high, Func<T, bool> predicate) { do_something() }
抛出 "cannot convert lambda expression to delegate type" 异常,而列表 class' 函数中发生完全相同的事情,即
intList = new List<int>() { 1000, 9102, 123, 41, 10, 52, 24, 8, 26 };
int i = intList.FirstOrDefault(b => b > 25);
为什么这不会引发错误,而这会引发错误?
Sort(intList.ToArray(), 0, 9, i => i > 25);
我的函数中传递的谓词参数看起来与 FirstOrDefalt 函数中的谓词参数完全一样!我真的需要为我的方法明确声明 lambda 表达式是一个 Func,还是我真的需要为我希望工作完全相同的东西创建一个匿名委托?这对我来说没有任何意义,因为 FirstOrDefault 签名绝对为零,表明它允许 Lambda 表达式,它所期望的只是一个 Func 委托,它与我正在做的完全一样。
这个有效:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main( string[] args )
{
var intList = new List<int> { 1000, 9102, 123, 41, 10, 52, 24, 8, 26 };
intList.ToArray()
.Sort( 0, 100, x => x > 27 );
}
}
public static class Ex
{
public static void Sort<T>( this T[] input, int low, int high, Func<T, bool> predicate )
{
input.ToList()
.ForEach( x => predicate( x ) );
}
}
}
编辑:
这是有效的,因为定义的谓词“predicate”表示一个以 T 的对象作为参数并返回布尔值的函数。我所做的就是创建一个与定义的谓词匹配的匿名函数……
我无法解释为什么或什么在 Schalks 代码中不起作用,因为我不知道他的代码...
编辑 2(添加完整代码示例):
如果您正在使用 List 的 Sort(int index, int count, IComparer comparer) 方法,您需要一个 IComparer 实例来比较列表项。如果您希望能够将比较器指定为 lambda 表达式,则需要一个 class 实现 IComparer,它在内部使用 lambda 表达式来比较项目。 (或者对于 .net 4.5,您可以使用 Comparer<T>.Create
Method 。)
这是一个完整的示例:
public class Program
{
public static void Main( string[] args )
{
var idiots = new List<Idiot>
{
new Idiot { Weapons = new[] { new Weapon { Damage = 10 }, new Weapon { Damage = 20 } } },
new Idiot { Weapons = new[] { new Weapon { Damage = 6 }, new Weapon { Damage = 100 } } },
new Idiot { Weapons = new[] { new Weapon { Damage = 45 }, new Weapon { Damage = 12 } } },
new Idiot { Weapons = new[] { new Weapon { Damage = 24 }, new Weapon { Damage = 5 } } },
};
foreach ( var i in idiots )
i.Weapons.QuickSort( 0, i.Weapons.Count() - 1, ( a, b ) => a.Damage.CompareTo( b.Damage ) );
//Solution using IEnumerable{T} extension methods
idiots.ForEach( x => x.Weapons = x.Weapons.OrderBy( y => y.Damage ).ToArray() );
}
}
public static class Ex
{
public static void QuickSort<T>(this IEnumerable<T> input, int low, int high, Func<T, T, Int32> comparer)
{
input
.ToList()
.Sort( low, high, new FunctionalComparer<T>( comparer ) );
}
}
public class FunctionalComparer<T> : IComparer<T>
{
private readonly Func<T, T, Int32> comparer;
public FunctionalComparer(Func<T, T, Int32> comparer)
{
this.comparer = comparer;
}
public Int32 Compare(T x, T y)
{
return comparer( x, y );
}
public static IComparer<T> Create(Func<T, T, Int32> comparer)
{
return new FunctionalComparer<T>( comparer );
}
}
public class Idiot
{
public Weapon[] Weapons { get; set; }
}
public class Weapon
{
public Int32 Damage { get; set; }
}
FunctionalComparer 实现 IComparer 并根据给定的 lambda 表达式比较两个对象。
QuickSort 创建 FunctionalComparer 的实例(使用给定的表达式)并使用该实例对项目进行排序。
但是您可以使用 IEnumerable 扩展方法来执行此操作,而不是编写所有这些代码。
为什么当我在自定义方法的谓词参数中传递 lambda 表达式(即 p => p.Damage)时,定义如下:
public static void Sort(T[] input, int low, int high, Func<T, bool> predicate) { do_something() }
抛出 "cannot convert lambda expression to delegate type" 异常,而列表 class' 函数中发生完全相同的事情,即
intList = new List<int>() { 1000, 9102, 123, 41, 10, 52, 24, 8, 26 };
int i = intList.FirstOrDefault(b => b > 25);
为什么这不会引发错误,而这会引发错误?
Sort(intList.ToArray(), 0, 9, i => i > 25);
我的函数中传递的谓词参数看起来与 FirstOrDefalt 函数中的谓词参数完全一样!我真的需要为我的方法明确声明 lambda 表达式是一个 Func,还是我真的需要为我希望工作完全相同的东西创建一个匿名委托?这对我来说没有任何意义,因为 FirstOrDefault 签名绝对为零,表明它允许 Lambda 表达式,它所期望的只是一个 Func 委托,它与我正在做的完全一样。
这个有效:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main( string[] args )
{
var intList = new List<int> { 1000, 9102, 123, 41, 10, 52, 24, 8, 26 };
intList.ToArray()
.Sort( 0, 100, x => x > 27 );
}
}
public static class Ex
{
public static void Sort<T>( this T[] input, int low, int high, Func<T, bool> predicate )
{
input.ToList()
.ForEach( x => predicate( x ) );
}
}
}
编辑:
这是有效的,因为定义的谓词“predicate”表示一个以 T 的对象作为参数并返回布尔值的函数。我所做的就是创建一个与定义的谓词匹配的匿名函数……
我无法解释为什么或什么在 Schalks 代码中不起作用,因为我不知道他的代码...
编辑 2(添加完整代码示例):
如果您正在使用 List 的 Sort(int index, int count, IComparer comparer) 方法,您需要一个 IComparer 实例来比较列表项。如果您希望能够将比较器指定为 lambda 表达式,则需要一个 class 实现 IComparer,它在内部使用 lambda 表达式来比较项目。 (或者对于 .net 4.5,您可以使用 Comparer<T>.Create
Method 。)
这是一个完整的示例:
public class Program
{
public static void Main( string[] args )
{
var idiots = new List<Idiot>
{
new Idiot { Weapons = new[] { new Weapon { Damage = 10 }, new Weapon { Damage = 20 } } },
new Idiot { Weapons = new[] { new Weapon { Damage = 6 }, new Weapon { Damage = 100 } } },
new Idiot { Weapons = new[] { new Weapon { Damage = 45 }, new Weapon { Damage = 12 } } },
new Idiot { Weapons = new[] { new Weapon { Damage = 24 }, new Weapon { Damage = 5 } } },
};
foreach ( var i in idiots )
i.Weapons.QuickSort( 0, i.Weapons.Count() - 1, ( a, b ) => a.Damage.CompareTo( b.Damage ) );
//Solution using IEnumerable{T} extension methods
idiots.ForEach( x => x.Weapons = x.Weapons.OrderBy( y => y.Damage ).ToArray() );
}
}
public static class Ex
{
public static void QuickSort<T>(this IEnumerable<T> input, int low, int high, Func<T, T, Int32> comparer)
{
input
.ToList()
.Sort( low, high, new FunctionalComparer<T>( comparer ) );
}
}
public class FunctionalComparer<T> : IComparer<T>
{
private readonly Func<T, T, Int32> comparer;
public FunctionalComparer(Func<T, T, Int32> comparer)
{
this.comparer = comparer;
}
public Int32 Compare(T x, T y)
{
return comparer( x, y );
}
public static IComparer<T> Create(Func<T, T, Int32> comparer)
{
return new FunctionalComparer<T>( comparer );
}
}
public class Idiot
{
public Weapon[] Weapons { get; set; }
}
public class Weapon
{
public Int32 Damage { get; set; }
}
FunctionalComparer 实现 IComparer 并根据给定的 lambda 表达式比较两个对象。 QuickSort 创建 FunctionalComparer 的实例(使用给定的表达式)并使用该实例对项目进行排序。
但是您可以使用 IEnumerable 扩展方法来执行此操作,而不是编写所有这些代码。