【问题标题】:How to correctly read the method signature of the .Any function in C#如何正确读取 C# 中 .Any 函数的方法签名
【发布时间】:2020-02-19 18:15:10
【问题描述】:

我真的很喜欢使用 C# 提供的聚合函数,例如 .Any(),但我很难理解我的选项只是从方法签名中看到的:

有人可以帮助我更好地理解(Func 谓词)的含义吗?我知道我通常在这里使用 lamda 函数。但是,我不明白它是如何转化为 Func 的。

【问题讨论】:

  • 它是一个将字符串作为输入并返回 bool 的函数(方法)
  • 你看Func的文档了吗?
  • 是的,是的,我做到了。但是,让了解某个主题的人用自己的话解释它通常会有所帮助。单一来源的文档会受到各种主要影响。

标签: c# .net


【解决方案1】:
(extension) bool IEnumerable<string>.Any<string>(Func<string, bool> predicate)(+ 1 overload)
Determines whether any element of a sequence satisfies a condition.

Exceptions:
  ArgumentNullException

意思是:

  • 您可以将此作为扩展方法调用。
  • IEnumerable&lt;string&gt; 上,您可以对其进行迭代,从而得到stringstring 是包含文本的类型。
  • 方法的名字是Any
  • 它有一个类型参数,设置为string。您可能可以在IEnumerable&lt;T&gt; 上调用它,其中T 不是string
  • 它接受一个Func&lt;string, bool&gt;predicate,这是一个函数的委托,该函数接受一个string作为输入参数并返回一个bool
  • 该方法还有另一个重载,它采用不同的参数。
  • 方法文档说它“确定序列的任何元素是否满足条件”。我们可以假设它遍历了 IEnumerable&lt;string&gt; 调用 Func&lt;string, bool&gt; 传递字符串,从 IEnumerable&lt;string&gt; 传递每个值,并返回是否为其中任何一个得到true
  • 该方法被记录为抛出一个ArgumentNullException,假设你传递了一个null

如果我们在网上查找它,我们会在官方文档中找到Enumerable.Any。在那里我们可以看到其他重载以及一些示例。

这是一个:

Pet[] pets =
        { new Pet { Name="Barley", Age=8, Vaccinated=true },
          new Pet { Name="Boots", Age=4, Vaccinated=false },
          new Pet { Name="Whiskers", Age=1, Vaccinated=false } };

    // Determine whether any pets over age 1 are also unvaccinated.
    bool unvaccinated =
        pets.Any(p => p.Age > 1 && p.Vaccinated == false);

我们看到Pet 的数组,我们在上面调用Any。因此,在这种情况下,类型参数是Pet 而不是string,因为Pet 的数组是您可以迭代的东西,它会为您提供Pet 类型的元素...我说Pet 的数组是IEnumerable&lt;Pet&gt;... 因此我们调用Any&lt;Pet&gt;

我们观察到参数是一个 lambda 表达式:p =&gt; p.Age &gt; 1 &amp;&amp; p.Vaccinated == false

这个 lambda 表示一个接受参数 p 的匿名函数。由于我们知道我们正在使用Any&lt;Pet&gt;,并且我们知道Any&lt;Pet&gt; 想要一个接受Pet 并返回bool 的函数的委托,我们知道p 是一个Pet

匿名函数接受Petp比较属性Age1以及属性Vaccinatedfalse,如果Age大于1,则返回trueVaccinated 是假的。

查看数组中的值,我们可以看到第二项(Name"Boots" 之一)的Age 大于1Vaccinatedfalse。因此,匿名函数应该为那个Pet返回true

如果predicate(匿名函数)对于任何元素是true,则Any 返回true,我们期望Any 在这种情况下返回true。官方文档中的示例描述和预期输出证实了这一点。

如果我们仍有疑问,当然可以尝试运行代码:code on SharpLab。预期的输出是“有超过一岁的未接种疫苗的动物。”。


如果你想更进一步,可以搜索reference implementation of Enumerable.Any

如果你知道去哪里看,你可以得到.NET Core source for Enumerable.Any不保证会留在那里,reectoring 可以把它放在其他地方。

您可能还对有关extension methods 的文档感兴趣。


另见What is Func, how and when is it used

【讨论】:

    【解决方案2】:

    但是,这又是如何转化为 Func 的呢?

    嗯,首先我们需要知道 Func 是什么。

    让我们看看Funcdeclared

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

    我们可以看到Func 是一个代表。如果您不知道代表是什么,那么有一些奇妙的页面可以告诉您有关它们的信息:123

    与你传入的 lambda 表达式有什么关系?

    声明说Func 是一个接受T 类型参数并返回TResult 的委托。从Any的签名中,我们可以看出Tstring,而TResultbool

    这意味着您可以转换一个 lambda 表达式(或一个方法组),它接受 string 作为参数并将 bool 返回到 Func&lt;string, bool&gt; 的实例。

    假设你像这样打电话给Any

    something.Any(x => x.Length > 10)
    

    从参数类型,编译器推断lambda表达式必须取string,所以x的类型必须是string。并且 lambda 表达式还必须返回一个 bool,它确实如此,所以我们很好! lambda 表达式被转换为Func&lt;string, bool&gt; 的实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多