-2

Is there a more concise way to achieve code reuse such as below without the foreach loop?

IEnumerable<Stream> GetStreams() {
    // nope
    // yield return GetStreamsHelper(); 

    // nope
    // return GetStreamsHelper(); 

    // yup
    foreach (var x in GetStreamsHelper()) {
        yield return x;
    }
}

IEnumerable<Stream> GetStreamsHelper() {
   using (var stream = OpenStream()) {
        yield return stream;
   }
}

Here's a more complete example of what I'm trying to achive:

    class MoreCompleteExample {
        IEnumerable<Stream> GetStreams() {
            string[] files = new[] { "f1", "f2" };
            foreach (var f in files) {
                // HERE I WANT TO USE A HELPER METHOD
                // NOTHING SEEMS TO WORK EXCEPT A foreach
                // PERHAPS THERE IS A LINQ-y WAY TO WRITE THE foreach?
                //return GetStreamsHelper(f);                    
                //yield return GetStreamsHelper(f);                    
                foreach (var x in GetStreamsHelper(f)) {
                    yield return x;
                }

            }
        }

        IEnumerable<Stream> GetStreamsHelper(string filename) {
            using (var stream = new FileStream(filename, FileMode.Open)) {
                Diddle(stream);
                yield return stream;
                Caress(stream);
            }
        }
        void Diddle(Stream stream) { /* show the stream some love */ }
        void Caress(Stream stream) { /* that was nice but i gotsa go */ }

    }
CoderBrien
  • 663
  • 1
  • 7
  • 22
  • Why not just return the ienumerable (no yield) in GetStreams? – KristoferA Jul 08 '16 at 00:23
  • 1
    Possible duplicate of [Nested yield return with IEnumerable](http://stackoverflow.com/questions/1270024/nested-yield-return-with-ienumerable) – Guvante Jul 08 '16 at 00:24
  • @KristoferA doesn't compile. – CoderBrien Jul 08 '16 at 00:24
  • Doesn't compile in what way? It looks fine. Are you showing us everything? – DavidG Jul 08 '16 at 00:25
  • @Guvante I saw that article, but it doesn't directly answer my question... unless you are implying the answer is "no, there is no better way". I'm thinking of some extension method or something that might express the foreach loop. – CoderBrien Jul 08 '16 at 00:25
  • Am I crazy or something? It really does not compile (ie is not valid code). Are you saying it does for you??? – CoderBrien Jul 08 '16 at 00:27
  • Of course it will compile, `return GetStreamsHelper()` returns the same type so it has no reason to fail. – DavidG Jul 08 '16 at 00:29
  • @DavidG hahaha.... nope sir. assumptions abound. – CoderBrien Jul 08 '16 at 00:31
  • 1
    What assumption? Either I am right or you are not showing us your actual code. Which is it? – DavidG Jul 08 '16 at 00:32
  • @DavidG Uggh... might be resharper screwing me... was getting "iterator cannot contain a return statement error message" ... investigating. – CoderBrien Jul 08 '16 at 00:34
  • 1
    Just to show you it compiles... http://ideone.com/0NzfcP – DavidG Jul 08 '16 at 00:37
  • @DavidG Ok, I see the problem. straight return of an iterator is fine, but my code actually tries to use a helper method to yield an element. i added a more complete class to the question. Thanks! – CoderBrien Jul 08 '16 at 00:39
  • OK, firstly why does `GetStreamsHelper` return an enumerable? Just return the stream. Secondly, remember that having the stream creation inside a `using` block will dispose of it immediately. – DavidG Jul 08 '16 at 00:41
  • @DavidG stream is NOT disposed until returning to (continuing in) the iterator if I'm yielding all the way down. that's the point of using iterators. plus i've got more code than just the `using` in my real code base. – CoderBrien Jul 08 '16 at 00:44
  • 2
    Very well, I give up now. If you are going to drip feed us code and detail, there's nothing more I can do. – DavidG Jul 08 '16 at 00:48
  • @DavidG Thanks for your input. – CoderBrien Jul 08 '16 at 00:50

1 Answers1

1

You have to enumerate through your collection to use yield return on it. You can change your code to the next one if you don’t want to iterate through collection inside your method:

IEnumerable<Stream> GetStreams() {
    return GetStreamsHelper(); 
}

And then you will iterate through the collection ouside of your method.

Ivan Yurchenko
  • 3,762
  • 1
  • 21
  • 35