Andy Pook commented on LUCENENET-469:

bq. Wow, do I sound so closed minded?
Ha. No not at all :) more worried I just not seeing the whole picture.

bq. not sure if the state is actually being "iterated over" ... 
Well, in so far as {{Next}} moves a set of values one step forward, it can 
certainly be thought of that way. I think of these like a cursor over a sql 
table. You can foreach over the rows. How the data is actually retrieved is 
abstracted. It could be one at a time, batches, all of them, cached... At the 
foreach level you just call Next to inspect the values of the next item.

bq. {{IEnumerable<T>}} is just an interface - it doesn't actually define any 
Right, this is one of those language syntax enabling things. You actually don't 
need to specify the interface. As long as the class implements 
{{GetEnumerator()}} then foreach will work. 

bq. So then we end up with some behavior that doesn't fit the mold.
True. But that's completely normal.
Imagine an enumerator over a Stream that pulls a line of text at a time. What 
would happen if you called {{myStream.Seek(...)}} inside the loop? Or a foreach 
over a Dictionary and call {{myDictionary.Add(...)}}? The behavior is to either 
throw (because the Dictionary.Enumerator protects against this) or some 
undefined behavior depending on which Stream/Reader or underlying storage is 
being used. Having overridden implementations with different behaviors is also 
to be expected. Many hours of fun to be had following Stream/TextReader etc. 
There's no guarantee that descendant classes will have similar behavior at he 

My theory was to enable foreach that would produce items representing the 
values of the Enum that change when its Next is called. This would be entirely 
an overlay/facade. All the existing members would remain presenting a dual api.
This way copy/pasting code from Java is still possible (modulo c# style 
properties). But the while style can be refactored to foreach. Or green field 
dev can be done in whichever style the dev likes.

All linq style stuff will work. I don't think the "extra" (Seek etc) are a 
problem. Most of them aren't composable as they return a single item or perfrom 
some op over the "collection". I mean for example you probably wouldn't call 
{{SeekExact}} from inside a foreach, in the same way you would use a dictionary 
indexer if you were foreach'ing over it. Or call {{Sort}} inside a foreach over 
a List.
Those that are composable (ie the various {{Docs}} methods) will work (assuming 
the {{DocsEnum}} is converted. So you could image 
{{terms.Docs(...).Where(d=>...).Select(...)}} working. But I would expect them 
to be at the beginning of the chain.
I guess you could image a few extra linq style extensions for special cases. 
But once you're into enumerable land it does cause some restrictions. Unless 
you want to get into rewriting expressions trees (runs away screaming).

You are quite right, trying to fit this in such that it's consistent across the 
class hierarchies is going to be a challenge for sure :)

I'm away this weekend but I'll try to put together a PR with a few 
examples/tests new week to see if it'll work out.

> Convert Java Iterator classes to implement IEnumerable<T>
> ---------------------------------------------------------
>                 Key: LUCENENET-469
>                 URL: https://issues.apache.org/jira/browse/LUCENENET-469
>             Project: Lucene.Net
>          Issue Type: Sub-task
>          Components: Lucene.Net Contrib, Lucene.Net Core
>    Affects Versions: Lucene.Net 2.9.4, Lucene.Net 2.9.4g, Lucene.Net 3.0.3, 
> Lucene.Net 4.8.0
>         Environment: all
>            Reporter: Christopher Currens
>             Fix For: Lucene.Net 4.8.0
> The Iterator pattern in Java is equivalent to IEnumerable in .NET.  Classes 
> that were directly ported in Java using the Iterator pattern, cannot be used 
> with Linq or foreach blocks in .NET.
> {{Next()}} would be equivalent to .NET's {{MoveNext()}}, and in the below 
> case, {{Term()}} would be as .NET's {{Current}} property.  In cases as below, 
> it will require {{TermEnum}} to become an abstract class with {{Term}} and 
> {{DocFreq}} properties, which would be returned from another class or method 
> that implemented {{IEnumerable<TermEnum>}}.
> {noformat} 
>       public abstract class TermEnum : IDisposable
>       {
>               public abstract bool Next();
>               public abstract Term Term();
>               public abstract int DocFreq();
>               public abstract void  Close();
>               public abstract void Dispose();
>       }
> {noformat} 
> would instead look something like:
> {noformat} 
>       public class TermFreq
>       {
>               public abstract Term { get; }
>               public abstract int { get; }
>       }
>         public abstract class TermEnum : IEnumerable<TermFreq>, IDisposable
>         {
>                 // ...
>         }
> {noformat}
> Keep in mind that it is important that if the class being converted 
> implements {{IDisposable}}, the class that is enumerating the terms (in this 
> case {{TermEnum}}) should inherit from both {{IEnumerable<T>}} *and* 
> {{IDisposable}}.  This won't be any change to the user, as the compiler 
> automatically calls {{IDisposable}} when used in a {{foreach}} loop.

This message was sent by Atlassian JIRA

Reply via email to