Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
屈服!运算符-实现和可能的C#等价物_C#_F#_Ienumerable_Yield_Enumerators - Fatal编程技术网

屈服!运算符-实现和可能的C#等价物

屈服!运算符-实现和可能的C#等价物,c#,f#,ienumerable,yield,enumerators,C#,F#,Ienumerable,Yield,Enumerators,我现在正在学习F#,我真的很喜欢收益(收益率)运算符。不仅是因为它的名字,当然也因为它的功能 屈服操作符基本上允许您从序列表达式中生成序列的所有元素。这对于组合枚举数很有用。由于我经常遇到大型、复杂的枚举数,我对我们可以使用的策略感兴趣,这些策略可以将它们分解,并将它们与简单的枚举数组合起来 不幸的是,屈服了运算符在C#中不可用。据我所知,它就像一个foreach(源代码中的var x)产生x

我现在正在学习F#,我真的很喜欢
收益(收益率)运算符。不仅是因为它的名字,当然也因为它的功能

屈服
操作符基本上允许您从序列表达式中生成序列的所有元素。这对于组合枚举数很有用。由于我经常遇到大型、复杂的枚举数,我对我们可以使用的策略感兴趣,这些策略可以将它们分解,并将它们与简单的枚举数组合起来

不幸的是,
屈服了运算符在C#中不可用。据我所知,它就像一个
foreach(源代码中的var x)产生x
  • 那么F#编译器在这里到底做什么呢?(是的,我也可以用反射器来观察,但我想更详细地描述一下这个机制)
为了在C#中实现类似的构造,我探索了多种方法,但没有一种方法像
yield运算符,我也不确定它们的复杂性。如果我的BigO号码是正确的,有人可以提供输入吗

  • 将枚举数分解为多个私有枚举数,然后从公共枚举数生成每个元素:

    foreach (var x in part1()) yield x
    foreach (var x in part2()) yield x
    
    这将有效地导致每个元素的“双倍收益”。那是O(2n)吗?(或者可能更糟?)无论如何,使用这种方法可以阻止我使用
    收益率中断来自我的任何子部分

  • 将枚举数分解为多个私有枚举数,然后从公共枚举数中提取所有私有枚举数:

    return part1().Concat(part2())
    
    我相信这与前面提到的解决方案没有什么不同,因为
    Concat()
    是以我上面概述的方式实现的


还有其他选择吗?

在当前版本的C#中,我认为除了每个。。。收益率返回
Concat
。我同意拥有
收益率会很好运算符,它将使某些构造更加优雅,但我怀疑这个特性是否会被列入“必备”列表,因为我们可以轻松地不使用它

您可能对此感兴趣,它引入了一个新的
yield-foreach
构造:

IEnumerable<XmlNode> Traverse(XmlNode n)
{
    yield return n;
    foreach (XmlNode c in n.ChildNodes)
        yield foreach Traverse(c);
}
IEnumerable遍历(XmlNode)
{
收益率n;
foreach(n.ChildNodes中的XmlNode c)
每条导线的屈服(c);
}

关于你关于复杂性的问题:在这两种情况下都是O(n)。不使用O(2n),因为它表示与O(n)(线性)相同的复杂性。我认为用目前的C#特性,你再也做不到比这更好的了…

没有直接对应的
屈服在C#中。您目前正面临着
foreach
yield return
的组合

然而,IIRC,LINQ提供了类似的东西,即
SelectMany
query操作符,它将C转换为multiple
from。。在..
子句中


(我希望我没有混淆两个不同的概念,但是IIRC,
yield!
SelectMany
本质上是“展平”投影;即对象的层次结构被“展平”为列表。)

关于编译器如何翻译
yield操作说明了第4.3节中的一种实现技术(特别是,他们跨越图7-9的示例说明了一般策略)。我不认为在C#中的迭代器块中有任何好的方法可以做到这一点-据我所知,您提出的解决方案,当递归使用时,它们都可能导致二次行为。您总是可以手动创建一个
NestedEnumerable
子类来获得性能优势,但与使用普通迭代器块相比,这将非常难看。

正如您引用的文章所指出的,当递归使用时,会有
屈服的实例
(相当于C#中假设的
收益率foreach
)为O(n),但
foreach。。。收益率返回…
是O(n^2)。@kvb:对,这就是我说的,如果不清楚,很抱歉。