This is an automated email from the ASF dual-hosted git repository.

paulirwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git


The following commit(s) were added to refs/heads/master by this push:
     new e40a52017 Replace SetOnce Get/Set with Value, #1069 (#1071)
e40a52017 is described below

commit e40a52017702aad5ce5fa5e36c981c1e9f462fc9
Author: Paul Irwin <[email protected]>
AuthorDate: Sat Dec 21 09:24:06 2024 -0700

    Replace SetOnce Get/Set with Value, #1069 (#1071)
---
 .../Index/MockRandomMergePolicy.cs                 |  3 +-
 src/Lucene.Net.Tests/Index/TestIndexWriter.cs      |  6 +--
 src/Lucene.Net.Tests/Util/TestSetOnce.cs           | 16 +++----
 src/Lucene.Net/Index/IndexWriterConfig.cs          |  2 +-
 src/Lucene.Net/Index/LogMergePolicy.cs             | 42 ++++++++---------
 src/Lucene.Net/Index/MergePolicy.cs                |  7 +--
 src/Lucene.Net/Index/TieredMergePolicy.cs          | 49 ++++++++++----------
 src/Lucene.Net/Index/UpgradeIndexMergePolicy.cs    |  4 +-
 src/Lucene.Net/Support/ObsoleteAPI/SetOnce.cs      | 43 ++++++++++++++++++
 src/Lucene.Net/Util/SetOnce.cs                     | 52 +++++++++++-----------
 10 files changed, 138 insertions(+), 86 deletions(-)

diff --git a/src/Lucene.Net.TestFramework/Index/MockRandomMergePolicy.cs 
b/src/Lucene.Net.TestFramework/Index/MockRandomMergePolicy.cs
index ed20cb2a2..c9a205b25 100644
--- a/src/Lucene.Net.TestFramework/Index/MockRandomMergePolicy.cs
+++ b/src/Lucene.Net.TestFramework/Index/MockRandomMergePolicy.cs
@@ -47,7 +47,8 @@ namespace Lucene.Net.Index
             int numSegments/* = segmentInfos.Count*/; // LUCENENET: IDE0059: 
Remove unnecessary value assignment
 
             JCG.List<SegmentCommitInfo> segments = new 
JCG.List<SegmentCommitInfo>();
-            ICollection<SegmentCommitInfo> merging = 
base.m_writer.Get().MergingSegments;
+            ICollection<SegmentCommitInfo> merging = 
base.m_writer.Value?.MergingSegments
+                ?? throw new InvalidOperationException("The writer has not 
been initialized"); // LUCENENET specific - throw exception if writer is null
 
             foreach (SegmentCommitInfo sipc in segmentInfos.Segments)
             {
diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriter.cs 
b/src/Lucene.Net.Tests/Index/TestIndexWriter.cs
index 7e8db747d..bda15ce0f 100644
--- a/src/Lucene.Net.Tests/Index/TestIndexWriter.cs
+++ b/src/Lucene.Net.Tests/Index/TestIndexWriter.cs
@@ -2877,7 +2877,7 @@ namespace Lucene.Net.Index
             SetOnce<IndexWriter> iwRef = new SetOnce<IndexWriter>();
             iwc.SetInfoStream(new TestPointInfoStream(iwc.InfoStream, new 
TestPointAnonymousClass(iwRef)));
             IndexWriter evilWriter = new IndexWriter(dir, iwc);
-            iwRef.Set(evilWriter);
+            iwRef.Value = evilWriter;
             for (int i = 0; i < 1000; i++)
             {
                 AddDoc(evilWriter);
@@ -2905,11 +2905,11 @@ namespace Lucene.Net.Index
             {
                 if ("startCommitMerge".Equals(message, 
StringComparison.Ordinal))
                 {
-                    iwRef.Get().KeepFullyDeletedSegments = false;
+                    iwRef.Value!.KeepFullyDeletedSegments = false;
                 }
                 else if ("startMergeInit".Equals(message, 
StringComparison.Ordinal))
                 {
-                    iwRef.Get().KeepFullyDeletedSegments = true;
+                    iwRef.Value!.KeepFullyDeletedSegments = true;
                 }
             }
         }
diff --git a/src/Lucene.Net.Tests/Util/TestSetOnce.cs 
b/src/Lucene.Net.Tests/Util/TestSetOnce.cs
index 4af4b812c..a6d6b3d20 100644
--- a/src/Lucene.Net.Tests/Util/TestSetOnce.cs
+++ b/src/Lucene.Net.Tests/Util/TestSetOnce.cs
@@ -56,7 +56,7 @@ namespace Lucene.Net.Util
                 try
                 {
                     Sleep(RAND.Next(10)); // sleep for a short time
-                    set.Set(new Integer(Convert.ToInt32(Name.Substring(2), 
CultureInfo.InvariantCulture)));
+                    set.Value = new Integer(Convert.ToInt32(Name.Substring(2), 
CultureInfo.InvariantCulture));
                     success = true;
                 }
                 catch (Exception e) when (e.IsInterruptedException())
@@ -76,24 +76,24 @@ namespace Lucene.Net.Util
         public virtual void TestEmptyCtor()
         {
             SetOnce<Integer> set = new SetOnce<Integer>();
-            Assert.IsNull(set.Get());
+            Assert.IsNull(set.Value);
         }
 
         [Test]
         public virtual void TestSettingCtor()
         {
             SetOnce<Integer> set = new SetOnce<Integer>(new Integer(5));
-            Assert.AreEqual(5, set.Get().value);
-            Assert.Throws<AlreadySetException>(() => set.Set(new Integer(7)));
+            Assert.AreEqual(5, set.Value?.value);
+            Assert.Throws<AlreadySetException>(() => set.Value = new 
Integer(7));
         }
 
         [Test]
         public virtual void TestSetOnce_mem()
         {
             SetOnce<Integer> set = new SetOnce<Integer>();
-            set.Set(new Integer(5));
-            Assert.AreEqual(5, set.Get().value);
-            Assert.Throws<AlreadySetException>(() => set.Set(new Integer(7)));
+            set.Value = new Integer(5);
+            Assert.AreEqual(5, set.Value.value);
+            Assert.Throws<AlreadySetException>(() => set.Value = new 
Integer(7));
         }
 
         [Test]
@@ -124,7 +124,7 @@ namespace Lucene.Net.Util
                 if (t.success)
                 {
                     int expectedVal = Convert.ToInt32(t.Name.Substring(2));
-                    Assert.AreEqual(expectedVal, t.set.Get().value, "thread " 
+ t.Name);
+                    Assert.AreEqual(expectedVal, t.set.Value?.value, "thread " 
+ t.Name);
                 }
             }
         }
diff --git a/src/Lucene.Net/Index/IndexWriterConfig.cs 
b/src/Lucene.Net/Index/IndexWriterConfig.cs
index 8ac9cdbe9..6025b670b 100644
--- a/src/Lucene.Net/Index/IndexWriterConfig.cs
+++ b/src/Lucene.Net/Index/IndexWriterConfig.cs
@@ -150,7 +150,7 @@ namespace Lucene.Net.Index
         ///           if this config is already attached to a writer. 
</exception>
         internal IndexWriterConfig SetIndexWriter(IndexWriter writer)
         {
-            this.writer.Set(writer);
+            this.writer.Value = writer;
             return this;
         }
 
diff --git a/src/Lucene.Net/Index/LogMergePolicy.cs 
b/src/Lucene.Net/Index/LogMergePolicy.cs
index 8ed22752d..3946e0f48 100644
--- a/src/Lucene.Net/Index/LogMergePolicy.cs
+++ b/src/Lucene.Net/Index/LogMergePolicy.cs
@@ -61,8 +61,8 @@ namespace Lucene.Net.Index
         public static readonly int DEFAULT_MERGE_FACTOR = 10;
 
         /// <summary>
-        /// Default maximum segment size.  A segment of this size 
-        /// or larger will never be merged. </summary> 
+        /// Default maximum segment size.  A segment of this size
+        /// or larger will never be merged. </summary>
         /// <seealso cref="MaxMergeDocs"/>
         public static readonly int DEFAULT_MAX_MERGE_DOCS = int.MaxValue;
 
@@ -125,7 +125,7 @@ namespace Lucene.Net.Index
         {
             get
             {
-                IndexWriter w = m_writer.Get();
+                IndexWriter w = m_writer.Value;
                 return w != null && w.infoStream.IsEnabled("LMP");
             }
         }
@@ -137,7 +137,7 @@ namespace Lucene.Net.Index
         {
             if (IsVerbose)
             {
-                m_writer.Get().infoStream.Message("LMP", message);
+                m_writer.Value?.infoStream.Message("LMP", message);
             }
         }
 
@@ -184,16 +184,17 @@ namespace Lucene.Net.Index
         }
 
         /// <summary>
-        /// Return the number of documents in the provided 
+        /// Return the number of documents in the provided
         /// <see cref="SegmentCommitInfo"/>, pro-rated by percentage of
-        /// non-deleted documents if 
+        /// non-deleted documents if
         /// <see cref="CalibrateSizeByDeletes"/> is set.
         /// </summary>
         protected virtual long SizeDocs(SegmentCommitInfo info)
         {
             if (m_calibrateSizeByDeletes)
             {
-                int delCount = m_writer.Get().NumDeletedDocs(info);
+                int delCount = m_writer.Value?.NumDeletedDocs(info)
+                    ?? throw new InvalidOperationException("The writer has not 
been initialized"); // LUCENENET specific - throw exception if writer is null
                 if (Debugging.AssertsEnabled) Debugging.Assert(delCount <= 
info.Info.DocCount);
                 return (info.Info.DocCount - (long)delCount);
             }
@@ -204,9 +205,9 @@ namespace Lucene.Net.Index
         }
 
         /// <summary>
-        /// Return the byte size of the provided 
+        /// Return the byte size of the provided
         /// <see cref="SegmentCommitInfo"/>, pro-rated by percentage of
-        /// non-deleted documents if 
+        /// non-deleted documents if
         /// <see cref="CalibrateSizeByDeletes"/> is set.
         /// </summary>
         protected virtual long SizeBytes(SegmentCommitInfo info)
@@ -220,7 +221,7 @@ namespace Lucene.Net.Index
 
         /// <summary>
         /// Returns <c>true</c> if the number of segments eligible for
-        /// merging is less than or equal to the specified 
+        /// merging is less than or equal to the specified
         /// <paramref name="maxNumSegments"/>.
         /// </summary>
         protected virtual bool IsMerged(SegmentInfos infos, int 
maxNumSegments, IDictionary<SegmentCommitInfo, bool> segmentsToMerge)
@@ -381,7 +382,7 @@ namespace Lucene.Net.Index
             if (Debugging.AssertsEnabled) Debugging.Assert(maxNumSegments > 0);
             if (IsVerbose)
             {
-                Message("findForcedMerges: maxNumSegs=" + maxNumSegments + " 
segsToMerge=" + 
+                Message("findForcedMerges: maxNumSegs=" + maxNumSegments + " 
segsToMerge=" +
                     string.Format(J2N.Text.StringFormatter.InvariantCulture, 
"{0}", segmentsToMerge));
             }
 
@@ -468,7 +469,7 @@ namespace Lucene.Net.Index
 
             var spec = new MergeSpecification();
             int firstSegmentWithDeletions = -1;
-            IndexWriter w = m_writer.Get();
+            IndexWriter w = m_writer.Value;
             if (Debugging.AssertsEnabled) Debugging.Assert(w != null);
             for (int i = 0; i < numSegments; i++)
             {
@@ -545,10 +546,10 @@ namespace Lucene.Net.Index
         /// <summary>
         /// Checks if any merges are now necessary and returns a
         /// <see cref="MergePolicy.MergeSpecification"/> if so.  A merge
-        /// is necessary when there are more than 
+        /// is necessary when there are more than
         /// <see cref="MergeFactor"/> segments at a given level.  When
         /// multiple levels have too many segments, this method
-        /// will return multiple merges, allowing the 
+        /// will return multiple merges, allowing the
         /// <see cref="MergeScheduler"/> to use concurrency.
         /// </summary>
         public override MergeSpecification FindMerges(MergeTrigger 
mergeTrigger, SegmentInfos infos)
@@ -564,7 +565,8 @@ namespace Lucene.Net.Index
             IList<SegmentInfoAndLevel> levels = new 
JCG.List<SegmentInfoAndLevel>();
             var norm = (float)Math.Log(m_mergeFactor);
 
-            ICollection<SegmentCommitInfo> mergingSegments = 
m_writer.Get().MergingSegments;
+            ICollection<SegmentCommitInfo> mergingSegments = 
m_writer.Value?.MergingSegments
+                ?? throw new InvalidOperationException("The writer has not 
been initialized"); // LUCENENET specific - throw exception if writer is null
 
             for (int i = 0; i < numSegments; i++)
             {
@@ -588,7 +590,7 @@ namespace Lucene.Net.Index
                     {
                         extra += " [skip: too large]";
                     }
-                    Message("seg=" + m_writer.Get().SegString(info) + " 
level=" + infoLevel.level + " size=" + 
String.Format(CultureInfo.InvariantCulture, "{0:0.00} MB", segBytes / 1024 / 
1024.0) + extra);
+                    Message("seg=" + m_writer.Value?.SegString(info) + " 
level=" + infoLevel.level + " size=" + 
string.Format(CultureInfo.InvariantCulture, "{0:0.00} MB", segBytes / 1024 / 
1024.0) + extra);
                 }
             }
 
@@ -696,7 +698,7 @@ namespace Lucene.Net.Index
                         }
                         if (IsVerbose)
                         {
-                            Message("  add merge=" + 
m_writer.Get().SegString(mergeInfos) + " start=" + start + " end=" + end);
+                            Message("  add merge=" + 
m_writer.Value?.SegString(mergeInfos) + " start=" + start + " end=" + end);
                         }
                         spec.Add(new OneMerge(mergeInfos));
                     }
@@ -726,9 +728,9 @@ namespace Lucene.Net.Index
         ///
         /// <para>The default value is <see cref="int.MaxValue"/>.</para>
         ///
-        /// <para>The default merge policy 
+        /// <para>The default merge policy
         /// (<see cref="LogByteSizeMergePolicy"/>) also allows you to set this
-        /// limit by net size (in MB) of the segment, using 
+        /// limit by net size (in MB) of the segment, using
         /// <see cref="LogByteSizeMergePolicy.MaxMergeMB"/>.</para>
         /// </summary>
         public virtual int MaxMergeDocs
@@ -752,4 +754,4 @@ namespace Lucene.Net.Index
             return sb.ToString();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/Lucene.Net/Index/MergePolicy.cs 
b/src/Lucene.Net/Index/MergePolicy.cs
index 325eef7f2..c697bbad9 100644
--- a/src/Lucene.Net/Index/MergePolicy.cs
+++ b/src/Lucene.Net/Index/MergePolicy.cs
@@ -658,7 +658,7 @@ namespace Lucene.Net.Index
         /// <seealso cref="SetOnce{T}"/>
         public virtual void SetIndexWriter(IndexWriter writer)
         {
-            this.m_writer.Set(writer);
+            this.m_writer.Value = writer;
         }
 
         /// <summary>
@@ -754,7 +754,8 @@ namespace Lucene.Net.Index
         protected virtual long Size(SegmentCommitInfo info)
         {
             long byteSize = info.GetSizeInBytes();
-            int delCount = m_writer.Get().NumDeletedDocs(info);
+            int delCount = m_writer.Value?.NumDeletedDocs(info)
+                ?? throw new InvalidOperationException("The writer has not 
been initialized"); // LUCENENET specific - throw exception if writer is null
             double delRatio = (info.Info.DocCount <= 0 ? 0.0f : 
((float)delCount / (float)info.Info.DocCount));
             if (Debugging.AssertsEnabled) Debugging.Assert(delRatio <= 1.0);
             return (info.Info.DocCount <= 0 ? byteSize : (long)(byteSize * 
(1.0 - delRatio)));
@@ -767,7 +768,7 @@ namespace Lucene.Net.Index
         /// </summary>
         protected bool IsMerged(SegmentInfos infos, SegmentCommitInfo info)
         {
-            IndexWriter w = m_writer.Get();
+            IndexWriter w = m_writer.Value;
             if (Debugging.AssertsEnabled) Debugging.Assert(w != null);
             bool hasDeletions = w.NumDeletedDocs(info) > 0;
             return !hasDeletions
diff --git a/src/Lucene.Net/Index/TieredMergePolicy.cs 
b/src/Lucene.Net/Index/TieredMergePolicy.cs
index a44f8da6c..a989ab18d 100644
--- a/src/Lucene.Net/Index/TieredMergePolicy.cs
+++ b/src/Lucene.Net/Index/TieredMergePolicy.cs
@@ -31,7 +31,7 @@ namespace Lucene.Net.Index
     /// an allowed number of segments per tier.  This is similar
     /// to <see cref="LogByteSizeMergePolicy"/>, except this merge
     /// policy is able to merge non-adjacent segment, and
-    /// separates how many segments are merged at once (<see 
cref="MaxMergeAtOnce"/>) 
+    /// separates how many segments are merged at once (<see 
cref="MaxMergeAtOnce"/>)
     /// from how many segments are allowed
     /// per tier (<see cref="SegmentsPerTier"/>).  This merge
     /// policy also does not over-merge (i.e. cascade merges).
@@ -100,8 +100,8 @@ namespace Lucene.Net.Index
         /// <summary>
         /// Gets or sets maximum number of segments to be merged at a time
         /// during "normal" merging.  For explicit merging (eg,
-        /// <see cref="IndexWriter.ForceMerge(int)"/> or 
-        /// <see cref="IndexWriter.ForceMergeDeletes()"/> was called), see 
+        /// <see cref="IndexWriter.ForceMerge(int)"/> or
+        /// <see cref="IndexWriter.ForceMergeDeletes()"/> was called), see
         /// <see cref="MaxMergeAtOnceExplicit"/>.  Default is 10.
         /// </summary>
         public virtual int MaxMergeAtOnce
@@ -122,7 +122,7 @@ namespace Lucene.Net.Index
 
         /// <summary>
         /// Gets or sets maximum number of segments to be merged at a time,
-        /// during <see cref="IndexWriter.ForceMerge(int)"/> or 
+        /// during <see cref="IndexWriter.ForceMerge(int)"/> or
         /// <see cref="IndexWriter.ForceMergeDeletes()"/>. Default is 30.
         /// </summary>
         public virtual int MaxMergeAtOnceExplicit
@@ -223,11 +223,11 @@ namespace Lucene.Net.Index
         /// <summary>
         /// Gets or sets the allowed number of segments per tier.  Smaller
         /// values mean more merging but fewer segments.
-        /// 
-        /// <para/><b>NOTE</b>: this value should be >= the 
+        ///
+        /// <para/><b>NOTE</b>: this value should be >= the
         /// <see cref="MaxMergeAtOnce"/> otherwise you'll force too much
         /// merging to occur.
-        /// 
+        ///
         /// <para/>Default is 10.0.
         /// </summary>
         public virtual double SegmentsPerTier
@@ -315,7 +315,8 @@ namespace Lucene.Net.Index
             {
                 return null;
             }
-            ICollection<SegmentCommitInfo> merging = 
m_writer.Get().MergingSegments;
+            ICollection<SegmentCommitInfo> merging = 
m_writer.Value?.MergingSegments
+                ?? throw new InvalidOperationException("The writer has not 
been initialized"); // LUCENENET specific - throw exception if writer is null
             ICollection<SegmentCommitInfo> toBeMerged = new 
JCG.HashSet<SegmentCommitInfo>();
 
             JCG.List<SegmentCommitInfo> infosSorted = new 
JCG.List<SegmentCommitInfo>(infos.AsList());
@@ -338,7 +339,7 @@ namespace Lucene.Net.Index
                     {
                         extra += " [floored]";
                     }
-                    Message("  seg=" + m_writer.Get().SegString(info) + " 
size=" + string.Format("{0:0.000}", segBytes / 1024 / 1024.0) + " MB" + extra);
+                    Message("  seg=" + m_writer.Value?.SegString(info) + " 
size=" + string.Format("{0:0.000}", segBytes / 1024 / 1024.0) + " MB" + extra);
                 }
 
                 minSegmentBytes = Math.Min(segBytes, minSegmentBytes);
@@ -449,7 +450,7 @@ namespace Lucene.Net.Index
                         MergeScore score = Score(candidate, hitTooLarge, 
mergingBytes);
                         if (Verbose())
                         {
-                            Message("  maybe=" + 
m_writer.Get().SegString(candidate) + " score=" + score.Score + " " + 
score.Explanation + " tooLarge=" + hitTooLarge + " size=" + 
string.Format("{0:0.000} MB", totAfterMergeBytes / 1024.0 / 1024.0));
+                            Message("  maybe=" + 
m_writer.Value?.SegString(candidate) + " score=" + score.Score + " " + 
score.Explanation + " tooLarge=" + hitTooLarge + " size=" + 
string.Format("{0:0.000} MB", totAfterMergeBytes / 1024.0 / 1024.0));
                         }
 
                         // If we are already running a max sized merge
@@ -479,7 +480,7 @@ namespace Lucene.Net.Index
 
                         if (Verbose())
                         {
-                            Message("  add merge=" + 
m_writer.Get().SegString(merge.Segments) + " size=" + string.Format("{0:0.000} 
MB", bestMergeBytes / 1024.0 / 1024.0) + " score=" + string.Format("{0:0.000}", 
bestScore.Score) + " " + bestScore.Explanation + (bestTooLarge ? " [max merge]" 
: ""));
+                            Message("  add merge=" + 
m_writer.Value?.SegString(merge.Segments) + " size=" + string.Format("{0:0.000} 
MB", bestMergeBytes / 1024.0 / 1024.0) + " score=" + string.Format("{0:0.000}", 
bestScore.Score) + " " + bestScore.Explanation + (bestTooLarge ? " [max merge]" 
: ""));
                         }
                     }
                     else
@@ -570,14 +571,15 @@ namespace Lucene.Net.Index
         {
             if (Verbose())
             {
-                Message("FindForcedMerges maxSegmentCount=" + maxSegmentCount 
+ 
-                    " infos=" + m_writer.Get().SegString(infos.Segments) + 
+                Message("FindForcedMerges maxSegmentCount=" + maxSegmentCount +
+                    " infos=" + m_writer.Value?.SegString(infos.Segments) +
                     " segmentsToMerge=" + 
string.Format(J2N.Text.StringFormatter.InvariantCulture, "{0}", 
segmentsToMerge));
             }
 
             JCG.List<SegmentCommitInfo> eligible = new 
JCG.List<SegmentCommitInfo>();
             bool forceMergeRunning = false;
-            ICollection<SegmentCommitInfo> merging = 
m_writer.Get().MergingSegments;
+            ICollection<SegmentCommitInfo> merging = 
m_writer.Value?.MergingSegments
+                ?? throw new InvalidOperationException("The writer has not 
been initialized"); // LUCENENET specific - throw exception if writer is null
             bool segmentIsOriginal = false;
             foreach (SegmentCommitInfo info in infos.Segments)
             {
@@ -631,7 +633,7 @@ namespace Lucene.Net.Index
                 OneMerge merge = new OneMerge(eligible.GetView(end - 
maxMergeAtOnceExplicit, maxMergeAtOnceExplicit)); // LUCENENET: Converted end 
index to length
                 if (Verbose())
                 {
-                    Message("add merge=" + 
m_writer.Get().SegString(merge.Segments));
+                    Message("add merge=" + 
m_writer.Value?.SegString(merge.Segments));
                 }
                 spec.Add(merge);
                 end -= maxMergeAtOnceExplicit;
@@ -644,7 +646,7 @@ namespace Lucene.Net.Index
                 OneMerge merge = new OneMerge(eligible.GetView(end - 
numToMerge, numToMerge)); // LUCENENET: Converted end index to length
                 if (Verbose())
                 {
-                    Message("add final merge=" + 
merge.SegString(m_writer.Get().Directory));
+                    Message("add final merge=" + 
merge.SegString(m_writer.Value?.Directory));
                 }
                 spec = new MergeSpecification();
                 spec.Add(merge);
@@ -657,13 +659,14 @@ namespace Lucene.Net.Index
         {
             if (Verbose())
             {
-                Message("findForcedDeletesMerges infos=" + 
m_writer.Get().SegString(infos.Segments) + " forceMergeDeletesPctAllowed=" + 
forceMergeDeletesPctAllowed);
+                Message("findForcedDeletesMerges infos=" + 
m_writer.Value?.SegString(infos.Segments) + " forceMergeDeletesPctAllowed=" + 
forceMergeDeletesPctAllowed);
             }
             JCG.List<SegmentCommitInfo> eligible = new 
JCG.List<SegmentCommitInfo>();
-            ICollection<SegmentCommitInfo> merging = 
m_writer.Get().MergingSegments;
+            ICollection<SegmentCommitInfo> merging = 
m_writer.Value?.MergingSegments
+                ?? throw new InvalidOperationException("The writer has not 
been initialized"); // LUCENENET specific - throw exception if writer is null
             foreach (SegmentCommitInfo info in infos.Segments)
             {
-                double pctDeletes = 100.0 * 
((double)m_writer.Get().NumDeletedDocs(info)) / info.Info.DocCount;
+                double pctDeletes = 100.0 * 
((double)m_writer.Value.NumDeletedDocs(info)) / info.Info.DocCount;
                 if (pctDeletes > forceMergeDeletesPctAllowed && 
!merging.Contains(info))
                 {
                     eligible.Add(info);
@@ -699,7 +702,7 @@ namespace Lucene.Net.Index
                 OneMerge merge = new OneMerge(eligible.GetView(start, end - 
start)); // LUCENENET: Converted end index to length
                 if (Verbose())
                 {
-                    Message("add merge=" + 
m_writer.Get().SegString(merge.Segments));
+                    Message("add merge=" + 
m_writer.Value.SegString(merge.Segments));
                 }
                 spec.Add(merge);
                 start = end;
@@ -719,13 +722,13 @@ namespace Lucene.Net.Index
 
         private bool Verbose()
         {
-            IndexWriter w = m_writer.Get();
+            IndexWriter w = m_writer.Value;
             return w != null && w.infoStream.IsEnabled("TMP");
         }
 
         private void Message(string message)
         {
-            m_writer.Get().infoStream.Message("TMP", message);
+            m_writer.Value?.infoStream.Message("TMP", message);
         }
 
         public override string ToString()
@@ -742,4 +745,4 @@ namespace Lucene.Net.Index
             return sb.ToString();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/Lucene.Net/Index/UpgradeIndexMergePolicy.cs 
b/src/Lucene.Net/Index/UpgradeIndexMergePolicy.cs
index 62a1e359c..2a9c84bd9 100644
--- a/src/Lucene.Net/Index/UpgradeIndexMergePolicy.cs
+++ b/src/Lucene.Net/Index/UpgradeIndexMergePolicy.cs
@@ -175,13 +175,13 @@ namespace Lucene.Net.Index
 
         private bool Verbose()
         {
-            IndexWriter w = m_writer.Get();
+            IndexWriter w = m_writer.Value;
             return w != null && w.infoStream.IsEnabled("UPGMP");
         }
 
         private void Message(string message)
         {
-            m_writer.Get().infoStream.Message("UPGMP", message);
+            m_writer.Value?.infoStream.Message("UPGMP", message);
         }
     }
 }
diff --git a/src/Lucene.Net/Support/ObsoleteAPI/SetOnce.cs 
b/src/Lucene.Net/Support/ObsoleteAPI/SetOnce.cs
new file mode 100644
index 000000000..7b9f11205
--- /dev/null
+++ b/src/Lucene.Net/Support/ObsoleteAPI/SetOnce.cs
@@ -0,0 +1,43 @@
+using System;
+#nullable enable
+
+namespace Lucene.Net.Util
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public partial class SetOnce<T>
+    {
+        /// <summary>
+        /// Sets the given object. If the object has already been set, an 
exception is thrown.
+        /// </summary>
+        [Obsolete("Use Value property instead. This method will be removed in 
4.8.0 release candidate."), 
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
+        public void Set(T? obj)
+        {
+            Value = obj;
+        }
+
+        /// <summary>
+        /// Returns the object set by <see cref="Set(T)"/> or <see 
cref="Value"/>.
+        /// </summary>
+        [Obsolete("Use Value property instead. This method will be removed in 
4.8.0 release candidate."), 
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
+        public T? Get()
+        {
+            return Value;
+        }
+    }
+}
diff --git a/src/Lucene.Net/Util/SetOnce.cs b/src/Lucene.Net/Util/SetOnce.cs
index fbf38c66e..6f76b1538 100644
--- a/src/Lucene.Net/Util/SetOnce.cs
+++ b/src/Lucene.Net/Util/SetOnce.cs
@@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
 using System.ComponentModel;
 using System.Runtime.Serialization;
 #endif
+#nullable enable
 
 namespace Lucene.Net.Util
 {
@@ -28,21 +29,21 @@ namespace Lucene.Net.Util
     /// <summary>
     /// A convenient class which offers a semi-immutable object wrapper
     /// implementation which allows one to set the value of an object exactly 
once,
-    /// and retrieve it many times. If <see cref="Set(T)"/> is called more 
than once,
+    /// and retrieve it many times. If the <see cref="Value"/> setter is 
called more than once,
     /// <see cref="AlreadySetException"/> is thrown and the operation
     /// will fail.
     /// <para/>
     /// @lucene.experimental
     /// </summary>
-    public sealed class SetOnce<T> // LUCENENET specific: Not implementing 
ICloneable per Microsoft's recommendation
+    public sealed partial class SetOnce<T> // LUCENENET specific: Not 
implementing ICloneable per Microsoft's recommendation
         where T : class // LUCENENET specific - added class constraint so we 
don't accept value types (which cannot be volatile)
     {
-        private volatile T obj = default;
+        private volatile T? obj;
         private readonly AtomicBoolean set;
 
         /// <summary>
         /// A default constructor which does not set the internal object, and 
allows
-        /// setting it by calling <see cref="Set(T)"/>.
+        /// setting it via <see cref="Value"/>.
         /// </summary>
         public SetOnce()
         {
@@ -51,39 +52,40 @@ namespace Lucene.Net.Util
 
         /// <summary>
         /// Creates a new instance with the internal object set to the given 
object.
-        /// Note that any calls to <see cref="Set(T)"/> afterwards will result 
in
+        /// Note that any calls to the <see cref="Value"/> setter afterwards 
will result in
         /// <see cref="AlreadySetException"/>
         /// </summary>
         /// <exception cref="AlreadySetException"> if called more than once 
</exception>
-        /// <seealso cref="Set(T)"/>
-        public SetOnce(T obj)
+        /// <seealso cref="Value"/>
+        public SetOnce(T? obj)
         {
             this.obj = obj;
             set = new AtomicBoolean(true);
         }
 
         /// <summary>
-        /// Sets the given object. If the object has already been set, an 
exception is thrown. </summary>
-        public void Set(T obj)
+        /// Gets or sets the object.
+        /// </summary>
+        /// <remarks>
+        /// This property's getter and setter replace the Get() and Set(T) 
methods in the Java version.
+        /// </remarks>
+        /// <exception cref="AlreadySetException">Thrown if the object has 
already been set.</exception>
+        public T? Value
         {
-            if (set.CompareAndSet(false, true))
-            {
-                this.obj = obj;
-            }
-            else
+            get => obj;
+            set
             {
-                throw new AlreadySetException();
+                if (set.CompareAndSet(false, true))
+                {
+                    this.obj = value;
+                }
+                else
+                {
+                    throw new AlreadySetException();
+                }
             }
         }
 
-        /// <summary>
-        /// Returns the object set by <see cref="Set(T)"/>. </summary>
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public T Get()
-        {
-            return obj;
-        }
-
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public object Clone()
         {
@@ -92,10 +94,10 @@ namespace Lucene.Net.Util
     }
 
     /// <summary>
-    /// Thrown when <see cref="SetOnce{T}.Set(T)"/> is called more than once. 
</summary>
+    /// Thrown when the <see cref="SetOnce{T}.Value"/> setter is called more 
than once. </summary>
     // LUCENENET specific - de-nested the class from SetOnce<T> to allow the 
test
     // framework to serialize it without the generic type.
-    // LUCENENET: It is no longer good practice to use binary serialization. 
+    // LUCENENET: It is no longer good practice to use binary serialization.
     // See: 
https://github.com/dotnet/corefx/issues/23584#issuecomment-325724568
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
     [Serializable]

Reply via email to