Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The behaviour here is perfectly normal. The reason is that you don't just have one subscription, you have many. And because of the cartesian product between the two observables in the query you have a larger number of <code>Do</code> than you might otherwise expect.</p> <p>Let's look at an alternative (but similar) query to yours.</p> <pre><code> var doCountX = 0; var doCountY = 0; Action dump = () =&gt; Console.WriteLine("doCountX = {0}, doCountY = {1}", doCountX, doCountY); var observable = new Subject&lt;int&gt;(); var streamX = observable.Do(x =&gt; doCountX++); var streamY = observable.Do(x =&gt; doCountY++); var query = from x in streamX from y in streamY select new { x, y }; query.Subscribe(z =&gt; Console.WriteLine("{0}, {1}", z.x, z.y)); dump(); for (var i = 1; i &lt;= 6; i++) { observable.OnNext(i); dump(); } </code></pre> <p>The output from this is:</p> <pre><code>doCountX = 0, doCountY = 0 doCountX = 1, doCountY = 0 1, 2 doCountX = 2, doCountY = 1 1, 3 2, 3 doCountX = 3, doCountY = 3 1, 4 2, 4 3, 4 doCountX = 4, doCountY = 6 1, 5 2, 5 3, 5 4, 5 doCountX = 5, doCountY = 10 1, 6 2, 6 3, 6 4, 6 5, 6 doCountX = 6, doCountY = 15 </code></pre> <p>There's the initial dump of <code>doCountX = 0, doCountY = 0</code> which is to be expected as this call to <code>dump()</code> occurs before any calls to <code>OnNext</code>.</p> <p>But when we get the first call to <code>OnNext</code> we don't get a value produced by the query because the second <code>streamY</code> observable hasn't yet been subscribed to.</p> <p>It's only when <code>OnNext</code> is called the second time do we get a value from the query which happens to be the first <code>OnNext</code> value paired with the second. Now this also creates a new subscriptions to <code>streamY</code>, waiting for the next value.</p> <p>So we've now got the first two values from <code>streamX</code> waiting for the next value from the sequence. So when <code>OnNext(3)</code> is called we get two results.</p> <p>Each time this happens you can see the number of <code>Do</code> calls incrementing <code>doCountY</code> just keep going up.</p> <p>In fact, given this very plain <code>SelectMany</code> query the formula is:</p> <pre><code>doCountY = n * (n - 1) / 2 </code></pre> <p>So with 6 values produced via <code>OnNext</code> you get <code>doCountY</code> equal to <code>6 * 5 / 2</code> or <code>15</code>.</p> <p>Running with 10 values gives <code>10 * 9 / 2</code> or <code>45</code> values.</p> <p>So a <code>SelectMany</code> in fact does many more subscriptions than you might think. This is often why you would generally only use it to chain together observables that only produce a single value each to prevent the exponential explosion of subscriptions.</p> <p>Does it make sense now?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload