NightOwl888 commented on code in PR #809:
URL: https://github.com/apache/lucenenet/pull/809#discussion_r1161174100


##########
src/Lucene.Net/Util/RollingBuffer.cs:
##########
@@ -57,25 +58,17 @@ public abstract class RollingBuffer<T>
         // How many valid Position are held in the
         // array:
         private int count;
-
-        protected RollingBuffer()
-        {
-            for (var idx = 0; idx < buffer.Length; idx++)
-            {
-                buffer[idx] = NewInstance(); // TODO GIVE ROLLING BUFFER A 
DELEGATE FOR NEW INSTANCE
-            }
-        }
+        private Func<T> factory;
 
         protected RollingBuffer(Func<T> factory)

Review Comment:
   I mocked up the above approach in a couple of different ways.
   
   OptionA is more complicated to implement for end users because they have to 
pass an extra generic type to both `RollingBuffer `and 
`IRollingBufferItemFactory`. However, inside the factory there is no casting 
required to see the state of the current buffer instance, as there is no cast 
to see the state in Java.
   
   OptionB is simpler to implement, but requires a cast from object to the 
buffer type. Although it is guaranteed to be that type, using an `is` cast as 
in my example makes it ambiguous what to do in the `else` case. 
   
   Some might consider OptionA to be overengineered. But given the rarity of 
the case that end users will implement their own `RollingBuffer` I personally 
think it is fine. And since it gives you a strong type for the buffer instance, 
it eliminates casting or any confusion over what type we are receiving or 
ambiguity when casting using `is`.
   
   If we go with OptionA, there is an extra `IRollingBuffer` interface needed 
to constrain us to a rolling buffer type without referring to any of its 
generic closing types. In this case we probably can add the public members that 
don't include `TItem` here instead of having an empty interface.
   
   ```c#
       internal class Program
       {
           static void Main(string[] args)
           {
               var a = new OptionA.MyBuffer();
               var b = new OptionB.MyBuffer();
   
               Console.WriteLine("Hello World!");
           }
       }
   
       namespace OptionA
       {
   
           public class Position
           {
           }
   
           public abstract class RollingBuffer<TItem, TRollingBuffer> : 
IRollingBuffer
               where TRollingBuffer : IRollingBuffer
           {
               protected RollingBuffer(IRollingBufferItemFactory<TItem, 
TRollingBuffer> itemFactory)
               {
                   TItem[] buffer = new TItem[10];
   
                   for (int idx = 0; idx < buffer.Length; idx++)
                   {
                       // This intermediate cast to object is required because 
of the generics, but it will never fail and is hidden from users.
                       buffer[idx] = 
itemFactory.Create((TRollingBuffer)(object)this);
                   }
               }
           }
   
           public interface IRollingBuffer // Interface required just so we can 
"own" the rolling buffer without a generic closing type
           {
           }
   
           public interface IRollingBufferItemFactory<out TItem, in 
TRollingBuffer>
                where TRollingBuffer : IRollingBuffer
           {
               TItem Create(TRollingBuffer rollingBuffer);
           }
   
           public class MyBuffer : RollingBuffer<Position, MyBuffer>
           {
               private object myState = new object();
   
               public MyBuffer()
                   : base(MyPositionFactory.Default)
               {
               }
   
               public class MyPositionFactory : 
IRollingBufferItemFactory<Position, MyBuffer>
               {
                   public static MyPositionFactory Default { get; } = new 
MyPositionFactory();
   
                   public Position Create(MyBuffer rollingBuffer)
                   {
                       var state = rollingBuffer.myState; // Now we can see the 
state
   
                       return new Position();
                   }
               }
           }
   
       }
   
       namespace OptionB
       {
           public class Position
           {
           }
   
           public abstract class RollingBuffer<T>
           {
               protected RollingBuffer(IRollingBufferItemFactory<T> itemFactory)
               {
                   T[] buffer = new T[10];
   
                   for (int idx = 0; idx < buffer.Length; idx++)
                   {
                       buffer[idx] = itemFactory.Create(this);
                   }
               }
           }
   
           public interface IRollingBufferItemFactory<out T>
           {
               T Create(object rollingBuffer);
           }
   
           public class MyBuffer : RollingBuffer<Position>
           {
               private object myState = new object();
   
               public MyBuffer()
                   : base(MyPositionFactory.Default)
               {
               }
   
               public class MyPositionFactory : 
IRollingBufferItemFactory<Position>
               {
                   public static MyPositionFactory Default { get; } = new 
MyPositionFactory();
   
                   public Position Create(object rollingBuffer)
                   {
                       if (rollingBuffer is MyBuffer buf)
                       {
                           var state = buf.myState; // Now we can see the state
                       }
                       // The else cannot technically happen, but if we return 
in the above block, we would need a return or throw after this line, which 
might not make any sense
   
                       return new Position();
                   }
               }
           }
       }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@lucenenet.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to