title: Is it possible to cache IEnumerable lazy evaluation results?
body: <p>I'm working on a method to find a config file path. This needs to do two passes: first find any existing config files, then go backwards and find the first writable path. </p>
  
  <p>Though overkill for my particular situation, this got me thinking: is it possible to have both lazy evaluation and prevent multiple enumeration?</p>
  
  <p>To illustrate what I mean, consider the following code:</p>
  
  <pre><code>public IEnumerable&lt;string&gt; GetPaths()
  {
      Console.WriteLine("GetPaths() Returning 'one'");
      yield return "one";
      Console.WriteLine("GetPaths() Returning 'two'");
      yield return "two";
      Console.WriteLine("GetPaths() Returning 'three'");
      yield return "three";
  }
  
  public bool IsWritable(string path) =&gt; false; // testing only 
  </code></pre>
  
  <p>If I run:</p>
  
  <pre><code>var paths = GetPaths();
  Console.WriteLine("Searching for existing file..");
  foreach (var path in paths)
  {
      if (File.Exists(path))
      {
          Console.WriteLine($"Found existing file '{path}'");
      }
  }
  
  Console.WriteLine("Searching for a writable path..");
  foreach (var path in paths.Reverse()) // NOTE: paths enumarated twice
  {
      if (IsWritable(path))
      {
          Console.WriteLine($"Found writable path '{path}'");
      }
  }
  
  Console.WriteLine("No paths found");
  </code></pre>
  
  <p>If the file 'one' exists, we get:</p>
  
  <pre><code>Searching for existing file..
  Returning 'one'
  Found existing file 'one'
  </code></pre>
  
  <p>If however, no files exist, we get:</p>
  
  <pre><code>Searching for existing file..
  Returning 'one'
  Returning 'two'
  Returning 'three'
  Searching for a writable path..
  Returning 'one'
  Returning 'two'
  Returning 'three'
  No paths found
  </code></pre>
  
  <p>(we wastefully enumerate the results of GetPaths() twice)</p>
  
  <hr>
  
  <p>One simple fix is to change the first line to:</p>
  
  <pre><code>var paths = GetPaths().ToList();
  </code></pre>
  
  <p>However, that means that even if the file <code>one</code> exists, the output would be:</p>
  
  <pre><code>Returning 'one'
  Returning 'two'
  Returning 'three'
  Searching for existing file..
  Found existing file 'one'
  </code></pre>
  
  <p>(as in, we unnecessarily enumerate the remainder of the list)</p>
  
  <hr>
  
  <p>Is there a (built-in) way to get both lazy enumeration and still prevent multiple enumeration?</p>
  
  <p>In other words, the desired output when 'one' exists is:</p>
  
  <pre><code>Searching for existing file..
  Returning 'one'
  Found existing file 'one'
  </code></pre>
  
  <p>and if no files exist:</p>
  
  <pre><code>Searching for existing file..
  Returning 'one'
  Returning 'two'
  Returning 'three'
  Searching for a writable path..
  No paths found
  </code></pre>