Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Well, there's a couple of things going on here.</p> <p><strong>First, you don't just have an extension method</strong>, you have an extension method <strong>iterator block</strong> - that's what you get when you use <code>yield return</code> to automatically implement the <code>IEnumerable&lt;&gt;</code> contract.</p> <p>It sounds like what you want to have happen is for <code>ActiveAccounts()</code> to return a null <code>IEnumerable&lt;Account&gt;</code>. What's actually happening is that for international reps you are returning null <em>as the first element of the IEnumerable</em>. I suspect that you may have tried using <code>return null</code> there but got a compiler error something like: </p> <blockquote> <p>Error: Cannot return a value from an iterator. Use the yield return statement to return a value, or yield break to end the iteration.</p> </blockquote> <p><strong>If what you intended is for the enumerable to be empty</strong>, what you want is <code>yield break</code> instead of <code>yield return null</code>. It's actually a better idea, generally, to return an empty sequence, as it allows the caller to avoid checking the return value. It also player nicer with technologies like LINQ, which use composition to assemble complex queries.</p> <p>The second issue is that the <code>if( rep == null )</code> precondition is not evaluated when you call <code>ActiveAccounts()</code>, but rather when you begin to enumerate the result of that call. That's probably not what you want - I'd imagine you want the precondition evaluated immediately.</p> <p>The way you resolve both these problems is to use a two-stage implementation:</p> <pre><code>public static class AccountExt { // apply preconditions, return null for international reps public static IEnumerable&lt;Account&gt; ActiveAccounts( this AccountRep rep ) { if( rep == null ) throw new ArgumentNullException( "rep" ); if( rep.IsInternational ) return null; // otherwise... return ActiveAccountsImpl( rep ); } // private implementation handles returning active accounts private static IEnumerable&lt;Account&gt; ActiveAccountsImpl( AccountRep rep ) { foreach( acc in rep.FetchAccounts() ) { if( acc.IsActive ) yield return acc; } } } </code></pre> <p>If you're willing to use LINQ, to can avoid the <code>Impl</code> version of the function:</p> <pre><code> public static IEnumerable&lt;Account&gt; ActiveAccounts( this AccountRep rep ) { if( rep == null ) throw new ArgumentNullException( "rep" ); if( rep.IsInternational ) return null; // otherwise, using LINQ to filter the accounts... return rep.FetchAccounts().Where( acc =&gt; acc.IsActive ); } </code></pre> <p>You can learn more about how iterator blocks <a href="http://csharpindepth.com/Articles/Chapter11/StreamingAndIterators.aspx" rel="nofollow noreferrer">here</a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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