LINQ SelectMany是绑定?

And*_*ith 18 c# linq

SelectMany将遍历一个对象树:

class Agency { List<Employees> Staff }

IEnumerable<Agency> Agencies

IEnumerable<Employee> =  
from anAgency in Agencies  
from anEmployee in anAgency.Staff. 
select anEmployee; 
Run Code Online (Sandbox Code Playgroud)

通常,我会先选择代理商,然后使用员工的内部实例来获取员工.但是在政府关闭的情况下,我只想列出每个人,看谁能覆盖.

在这种不适合我的对象模型的罕见情况下,我可以使用SelectMany来任意遍历树.

你怎么称呼这个遍历?交叉加入?这不是因为加入已经隐含在原子能机构对象的工作人员组成中.

它绑定了吗?我对bind一无所知.

除了Select之外没有别的名字吗?

Lee*_*Lee 48

SelectMany在C#中对应于Haskell (>>=)flatMapScala中的绑定.>>=Haskell 的签名是:

(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

所以bind是一个用于从另一个构造一个monadic值的操作.

在C#的情况下m在上述签名是IEnumerable,IObservable,IQueryable等.IEnumerable,SelectMany因此是

IEnumerable<A> -> (A -> IEnumerable<B>) -> IEnumerable<B>
Run Code Online (Sandbox Code Playgroud)

或者在C#中

public static IEnumerable<B> SelectMany<A, B>(this IEnumerable<A> first, Func<A, IEnumerable<B>> selector)
Run Code Online (Sandbox Code Playgroud)

bind的含义取决于monad类型,对于IEnumerable,输入序列中的每个元素用于创建新序列,并且生成的序列序列被展平以产生输出序列.

还有另一种结合方式可以使其更清晰.虽然monad通常用它们的bind实现来描述,但monad也必须支持另外两个操作,map并且join.

map 对应于C#中的Select,看起来像:

map :: Monad m => (a -> b) -> (ma -> m b)
Run Code Online (Sandbox Code Playgroud)

因此它是一种"结构保持"方式,可以在monadic值上提升常规函数.

join 有类型

join :: Monad m => m m a -> m a
Run Code Online (Sandbox Code Playgroud)

所以join用于展平嵌套的monadic值.在C#中,这看起来像

public static IEnumerable<A> Join<A>(this IEnumerable<IEnumerable<A>> nested)
Run Code Online (Sandbox Code Playgroud)

bind 可以用map和join来实现

m >>= f = join (map f m)
Run Code Online (Sandbox Code Playgroud)

所以回答原始问题,SelectMany对应于bindflatMap用其他语言.绑定不仅仅是扁平化,而是可以看作是一种转换,随后是嵌套的monadic值的扁平化(例如,序列中的序列IEnumerable<T>).joinfor IEnumerable<T>当前的linq扩展中不存在.