Func<>简单的英语运算符

本文关键字:英语 运算符 简单 Func | 更新日期: 2023-09-27 17:55:17

我正在考虑创建一个动态linq查询,其中Where运算符将根据用户的选择而有所不同,而且我对框架不太熟悉。似乎我需要使用 Func 运算符,并且我很难理解这种语法。

它有什么作用? 什么意思?有人可以帮助我了解它是如何使用的吗?

谢谢。

Func<>简单的英语运算符

Func<>只是一个预定义的委托模式:

protected bool SomeMethod(int input)
{
    return true;
}

这是一种相当标准的方法。您可以创建一个以此签名为目标的委托,如下所示:

public delegate bool MyMethodType(int input);

此委托仅适用于采用 1 个整数并返回布尔值的方法。Func<>试图通过使其通用来简化这一点:

public delegate T Func<T>();
public delegate U Func<T, U>(T input);

这实际上就是 Func<>,只是一个通用委托。这样,你可以说出所有这些事情:

Func<int, bool> myMethod = SomeMethod;
MyMethodType myMethod = SomeMethod;

就 LINQ 而言,您可能会使用速记表达式语法;编译器会将表达式转换为委托:

.Where(x => x.SomeProperty > 10);

此语句等效于:

.Where(delegate(int someProperty) { return someProperty > 10) })

这都是编译器语法糖。

Func<T>只是一个类型名称。它不是一种特殊的语法。

您需要考虑的是 lambda 表达式。例如,考虑一下:

myCollection.Where(item => item.Size == 10)

这意味着以下内容:获取集合myCollection中的所有项,检查每个项的Size属性是否等于10,并仅考虑这种情况的项。

还有

更多这样的运算符使用 lambda 表达式。MSDN上的LINQ查询有一个很好的介绍

只需记住Func<>的意思是"功能"。函数基本上是一个返回结果的方法。

例如:

  • Func<bool>的意思是"一个函数返回布尔值"
  • Func<string,bool>的意思是"一个函数仅将字符串作为输入参数并返回布尔"
  • Func<bool,string,int,string,bool>表示"一个函数需要 4 个输入参数分别为类型布尔值,字符串,整数和字符串...返回布尔值"

依此类推:<>之间列出的类型是按正确顺序排列的输入参数类型,除了最后一个是函数的返回类型。

现在,就Where而言,它需要一个Func<TSource, Boolean>作为论据,对吧?这意味着任何采用TSource输入参数并返回Boolean(又名bool)的方法都可以(TSource是集合中每个元素的类型Where)。

这意味着:Where将只保留所选方法将返回true的每个TSource

例:您希望筛选名字列表以仅保留以"T"开头的名字。

string[] firstnames = new string[] { "Albert", "Terry", "Bob", Tom", "Joe" };
string[] firstnamesBeginningWithT = firstnames.Where(beginsWithT).ToArray();

beginsWithT是这种方法:

bool beginsWithT(string firstname)
{
   return firstname.StartWith("T");
}

存在一种快捷方式,这使得创建此单行方法变得不必要beginsWithT该方法可能只使用一次:

string[] firstnamesBeginningWithT = firstnames.Where(firstname => firstname.StartWith("T")).ToArray();

这意味着"对于集合中的每个元素,让我们通过方便将其称为firstname,让我们看看它是否以 T 开头"。此语法调用"lambda 表达式",等效于"没有名称的即时方法",但与beginsWithT一样,您会注意到它将string作为输入并返回Boolean。因此,它是一种Func<string,bool>,符合Where的需要。

希望现在一切都更清楚了! :-)西特拉

Func不是

运算符 - 它只是一个泛型委托类型。如果你看一下不同"重载"的签名,它应该会变得更加清晰:

Func<TResult>
Func<T, TResult>
Func<T1, T2, TResult>

第一个是不带参数并返回值的函数,第二个是接受一个参数并返回一个值的函数,依此类推。

总而言之,它本质上是一个帮助程序类型,使你能够定义函数,而无需每次都单独定义委托类型。

现在,这些对动态 Linq 查询都没有多大帮助,但这就是您提出的......

Func<T>只是一个类型名称。它不是一种特殊的语法。

你需要把你的头缠绕在表达式树上。例如,考虑一下:

myCollection.Where(item => item.Size == 10)

如果myCollection的类型为 IQueryable<T> ,则编译器会将其转换为表示 lambda 表达式item => item.Size == 10表达式树。例如,如果您使用它来访问 SQL 数据库,则此表达式会自动转换为 SQL。

可以使用表达式树生成动态查询,如 MSDN 中所述。特别是,您将使用 Expression 类型中的许多静态方法来动态构造此类表达式树。