You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2017/08/13 16:33:37 UTC

[5/5] lucenenet git commit: API: Lucene.Net.Documents.Field: Added GetNumericType() method and refactored codecs, suggest, misc, spatial, and classification so they utilize the GetXXXValue() methods instead of GetNumericValue(). Added extension methods G

API: Lucene.Net.Documents.Field: Added GetNumericType() method and refactored codecs, suggest, misc, spatial, and classification so they utilize the GetXXXValue() methods instead of GetNumericValue(). Added extension methods GetXXXValueOrDefault() to easily retrieve the numeric value if it is not a concern that it could be null.


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/c22ef079
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/c22ef079
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/c22ef079

Branch: refs/heads/master
Commit: c22ef079bd29faaba88f4ca1293f0fc3c4ec32ba
Parents: beb4894
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Aug 13 22:35:30 2017 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Sun Aug 13 23:33:02 2017 +0700

----------------------------------------------------------------------
 .../Utils/DatasetSplitter.cs                    |  20 ++-
 .../SimpleText/SimpleTextStoredFieldsWriter.cs  |  30 ++--
 src/Lucene.Net.Misc/Document/LazyDocument.cs    | 115 ++++++++++++++++
 .../Suggest/DocumentDictionary.cs               |   4 +-
 .../Lucene3x/PreFlexRWStoredFieldsWriter.cs     |  33 +++--
 .../Index/BaseStoredFieldsFormatTestCase.cs     |   8 +-
 .../Util/LuceneTestCase.cs                      |   2 +
 src/Lucene.Net.TestFramework/Util/TestUtil.cs   |  10 +-
 .../Highlight/HighlighterTest.cs                |   3 +-
 src/Lucene.Net.Tests.Join/TestBlockJoin.cs      |   2 +-
 src/Lucene.Net.Tests.Spatial/SpatialExample.cs  |   2 +-
 .../Suggest/DocumentDictionaryTest.cs           |   8 +-
 .../DocumentValueSourceDictionaryTest.cs        |  22 +--
 src/Lucene.Net.Tests/Document/TestField.cs      |  22 +--
 .../Index/TestIndexWriterExceptions.cs          |  25 ++++
 .../Index/TestIndexableField.cs                 |  25 ++++
 .../Search/TestLiveFieldValues.cs               |   2 +-
 .../Search/TestNumericRangeQuery32.cs           |  24 ++--
 .../Search/TestNumericRangeQuery64.cs           |  24 ++--
 .../CompressingStoredFieldsWriter.cs            | 137 +++++--------------
 .../Lucene40/Lucene40StoredFieldsWriter.cs      |  33 +++--
 src/Lucene.Net/Document/Field.cs                | 116 ++++++++++++++--
 src/Lucene.Net/Index/DocValuesProcessor.cs      |   8 +-
 src/Lucene.Net/Index/IndexableField.cs          |  88 +++++++++---
 src/Lucene.Net/Lucene.Net.csproj                |   1 +
 .../Document/IndexableFieldExtensions.cs        |  99 ++++++++++++++
 26 files changed, 621 insertions(+), 242 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Classification/Utils/DatasetSplitter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Classification/Utils/DatasetSplitter.cs b/src/Lucene.Net.Classification/Utils/DatasetSplitter.cs
index 96af827..8204225 100644
--- a/src/Lucene.Net.Classification/Utils/DatasetSplitter.cs
+++ b/src/Lucene.Net.Classification/Utils/DatasetSplitter.cs
@@ -1,9 +1,10 @@
-using System;
-using System.IO;
 using Lucene.Net.Analysis;
 using Lucene.Net.Documents;
 using Lucene.Net.Index;
 using Lucene.Net.Search;
+using System;
+using System.Globalization;
+using System.IO;
 using Directory = Lucene.Net.Store.Directory;
 
 namespace Lucene.Net.Classification.Utils
@@ -107,9 +108,20 @@ namespace Lucene.Net.Classification.Utils
                             {
                                 doc.Add(new Field(storableField.Name, storableField.GetStringValue(), ft));
                             }
-                            else if (storableField.GetNumericValue() != null)
+                            else if (storableField.GetDoubleValue() != null) // LUCENENET specific - This will cast any numeric type an check whether there is a value without boxing/unboxing
                             {
-                                doc.Add(new Field(storableField.Name, storableField.GetNumericValue().ToString(), ft));
+                                // LUCENENET specific - need to pass invariant culture here (we are assuming the Field will be stored)
+                                // and we need to round-trip floating point numbers so we don't lose precision. 
+                                Type numericType = storableField.GetNumericType();
+                                if (typeof(float).Equals(numericType) || typeof(double).Equals(numericType))
+                                {
+                                    // LUCENENET: Need to specify the "R" for round-trip: http://stackoverflow.com/a/611564
+                                    doc.Add(new Field(storableField.Name, storableField.GetStringValue("R", CultureInfo.InvariantCulture), ft));
+                                }
+                                else
+                                {
+                                    doc.Add(new Field(storableField.Name, storableField.GetStringValue(CultureInfo.InvariantCulture), ft));
+                                }
                             }
                         }
                     }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Codecs/SimpleText/SimpleTextStoredFieldsWriter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Codecs/SimpleText/SimpleTextStoredFieldsWriter.cs b/src/Lucene.Net.Codecs/SimpleText/SimpleTextStoredFieldsWriter.cs
index 92d68ce..0676811 100644
--- a/src/Lucene.Net.Codecs/SimpleText/SimpleTextStoredFieldsWriter.cs
+++ b/src/Lucene.Net.Codecs/SimpleText/SimpleTextStoredFieldsWriter.cs
@@ -107,51 +107,53 @@ namespace Lucene.Net.Codecs.SimpleText
 
             Write(TYPE);
 
-            var n = field.GetNumericValue();
-
-            if (n != null)
+            // LUCENENET specific - To avoid boxing/unboxing, we don't
+            // call GetNumericValue(). Instead, we check the field type and then
+            // call the appropriate conversion method. 
+            Type numericType = field.GetNumericType();
+            if (numericType != null)
             {
-                if (n is sbyte? || n is short? || n is int?)
+                if (typeof(byte).Equals(numericType) || typeof(short).Equals(numericType) || typeof(int).Equals(numericType))
                 {
                     Write(TYPE_INT);
                     NewLine();
 
                     Write(VALUE);
-                    Write(((int)n).ToString(CultureInfo.InvariantCulture));
+                    Write(field.GetStringValue(CultureInfo.InvariantCulture));
                     NewLine();
                 }
-                else if (n is long?)
+                else if (typeof(long).Equals(numericType))
                 {
                     Write(TYPE_LONG);
                     NewLine();
 
                     Write(VALUE);
-                    Write(((long)n).ToString(CultureInfo.InvariantCulture));
+                    Write(field.GetStringValue(CultureInfo.InvariantCulture));
                     NewLine();
                 }
-                else if (n is float?)
+                else if (typeof(float).Equals(numericType))
                 {
                     Write(TYPE_FLOAT);
                     NewLine();
 
                     Write(VALUE);
-                    // LUCENENET: Need to specify the "R" for round-trip: http://stackoverflow.com/a/611564/181087
-                    Write(((float)n).ToString("R", CultureInfo.InvariantCulture));
+                    // LUCENENET: Need to specify the "R" for round-trip: http://stackoverflow.com/a/611564
+                    Write(field.GetStringValue("R", CultureInfo.InvariantCulture));
                     NewLine();
                 }
-                else if (n is double?)
+                else if (typeof(double).Equals(numericType))
                 {
                     Write(TYPE_DOUBLE);
                     NewLine();
 
                     Write(VALUE);
-                    // LUCENENET: Need to specify the "R" for round-trip: http://stackoverflow.com/a/611564/181087
-                    Write(((double)n).ToString("R", CultureInfo.InvariantCulture));
+                    // LUCENENET: Need to specify the "R" for round-trip: http://stackoverflow.com/a/611564
+                    Write(field.GetStringValue("R", CultureInfo.InvariantCulture));
                     NewLine();
                 }
                 else
                 {
-                    throw new ArgumentException("cannot store numeric type " + n.GetType());
+                    throw new ArgumentException("cannot store numeric type " + numericType);
                 }
             }
             else

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Misc/Document/LazyDocument.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Document/LazyDocument.cs b/src/Lucene.Net.Misc/Document/LazyDocument.cs
index 33b8b4a..f961bac 100644
--- a/src/Lucene.Net.Misc/Document/LazyDocument.cs
+++ b/src/Lucene.Net.Misc/Document/LazyDocument.cs
@@ -174,72 +174,187 @@ namespace Lucene.Net.Documents
                 return realValue;
             }
 
+            /// <summary>
+            /// The field's name
+            /// </summary>
             public virtual string Name
             {
                 get { return name; }
             }
 
+            /// <summary>
+            /// Gets the boost factor on this field.
+            /// </summary>
             public virtual float Boost
             {
                 get { return 1.0f; }
             }
 
+            /// <summary>
+            /// Non-null if this field has a binary value. </summary>
             public virtual BytesRef GetBinaryValue()
             {
                 return GetRealValue().GetBinaryValue();
             }
 
+            /// <summary>
+            /// The value of the field as a <see cref="string"/>, or <c>null</c>. If <c>null</c>, the <see cref="TextReader"/> value or
+            /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
+            /// <see cref="GetBinaryValue()"/> must be set.
+            /// </summary>
+            /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
             public virtual string GetStringValue()
             {
                 return GetRealValue().GetStringValue();
             }
 
+            /// <summary>
+            /// The value of the field as a <see cref="string"/>, or <c>null</c>. If <c>null</c>, the <see cref="TextReader"/> value or
+            /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
+            /// <see cref="GetBinaryValue()"/> must be set.
+            /// </summary>
+            /// <param name="provider">An object that supplies culture-specific formatting information. This parameter has no effect if this field is non-numeric.</param>
+            /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified provider
+            public virtual string GetStringValue(IFormatProvider provider) 
+            {
+                return GetRealValue().GetStringValue(provider);
+            }
+
+            /// <summary>
+            /// The value of the field as a <see cref="string"/>, or <c>null</c>. If <c>null</c>, the <see cref="TextReader"/> value or
+            /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
+            /// <see cref="GetBinaryValue()"/> must be set.
+            /// </summary>
+            /// <param name="format">A standard or custom numeric format string. This parameter has no effect if this field is non-numeric.</param>
+            /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified format
+            public virtual string GetStringValue(string format) 
+            {
+                return GetRealValue().GetStringValue(format);
+            }
+
+            /// <summary>
+            /// The value of the field as a <see cref="string"/>, or <c>null</c>. If <c>null</c>, the <see cref="TextReader"/> value or
+            /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
+            /// <see cref="GetBinaryValue()"/> must be set.
+            /// </summary>
+            /// <param name="format">A standard or custom numeric format string. This parameter has no effect if this field is non-numeric.</param>
+            /// <param name="provider">An object that supplies culture-specific formatting information. This parameter has no effect if this field is non-numeric.</param>
+            /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified format and provider
+            public virtual string GetStringValue(string format, IFormatProvider provider) 
+            {
+                return GetRealValue().GetStringValue(format, provider);
+            }
+
+            /// <summary>
+            /// The value of the field as a <see cref="TextReader"/>, or <c>null</c>. If <c>null</c>, the <see cref="string"/> value or
+            /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
+            /// <see cref="GetBinaryValue()"/> must be set.
+            /// </summary>
             public virtual TextReader GetReaderValue()
             {
                 return GetRealValue().GetReaderValue();
             }
 
+            [Obsolete("In .NET, use of this method will cause boxing/unboxing. Instead, call GetNumericType() to check the underlying type and call the appropriate GetXXXValue() method to retrieve the value.")]
             public virtual object GetNumericValue()
             {
                 return GetRealValue().GetNumericValue();
             }
 
+            /// <summary>
+            /// Gets the <see cref="Type"/> of the underlying value, or <c>null</c> if the value is not set or non-numeric.
+            /// <para/>
+            /// LUCENENET specific. In Java, the numeric type was determined by checking the type of  
+            /// <see cref="GetNumericValue()"/>. However, since there are no reference number
+            /// types in .NET, using <see cref="GetNumericValue()"/> so will cause boxing/unboxing. It is
+            /// therefore recommended to call this method to check the underlying type and the corresponding 
+            /// <c>Get*Value()</c> method to retrieve the value.
+            /// </summary>
+            // LUCENENET specific - Since we have no numeric reference types in .NET, this method was added to check
+            // the numeric type of the inner field without boxing/unboxing.
+            public virtual Type GetNumericType()
+            {
+                return GetRealValue().GetNumericType();
+            }
+
+            /// <summary>
+            /// Returns the field value as <see cref="byte"/> or <c>null</c> if the type
+            /// is non-numeric.
+            /// </summary>
+            /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
             // LUCENENET specific - created overload for Byte, since we have no Number class in .NET
             public virtual byte? GetByteValue()
             {
                 return GetRealValue().GetByteValue();
             }
 
+            /// <summary>
+            /// Returns the field value as <see cref="short"/> or <c>null</c> if the type
+            /// is non-numeric.
+            /// </summary>
+            /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
             // LUCENENET specific - created overload for Short, since we have no Number class in .NET
             public virtual short? GetInt16Value()
             {
                 return GetRealValue().GetInt16Value();
             }
 
+            /// <summary>
+            /// Returns the field value as <see cref="int"/> or <c>null</c> if the type
+            /// is non-numeric.
+            /// </summary>
+            /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
             // LUCENENET specific - created overload for Int32, since we have no Number class in .NET
             public virtual int? GetInt32Value()
             {
                 return GetRealValue().GetInt32Value();
             }
 
+            /// <summary>
+            /// Returns the field value as <see cref="long"/> or <c>null</c> if the type
+            /// is non-numeric.
+            /// </summary>
+            /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
             // LUCENENET specific - created overload for Int64, since we have no Number class in .NET
             public virtual long? GetInt64Value()
             {
                 return GetRealValue().GetInt64Value();
             }
 
+            /// <summary>
+            /// Returns the field value as <see cref="float"/> or <c>null</c> if the type
+            /// is non-numeric.
+            /// </summary>
+            /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
             // LUCENENET specific - created overload for Single, since we have no Number class in .NET
             public virtual float? GetSingleValue()
             {
                 return GetRealValue().GetSingleValue();
             }
 
+            /// <summary>
+            /// Returns the field value as <see cref="double"/> or <c>null</c> if the type
+            /// is non-numeric.
+            /// </summary>
+            /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
             // LUCENENET specific - created overload for Double, since we have no Number class in .NET
             public virtual double? GetDoubleValue()
             {
                 return GetRealValue().GetDoubleValue();
             }
 
+            /// <summary>
+            /// Returns the <see cref="Documents.FieldType"/> for this field as type <see cref="Documents.FieldType"/>. </summary>
+            public virtual FieldType FieldType
+            {
+                get { return GetRealValue().IndexableFieldType as FieldType; }
+            }
+
+            /// <summary>
+            /// Returns the <see cref="Documents.FieldType"/> for this field as type <see cref="IIndexableFieldType"/>. </summary>
             public virtual IIndexableFieldType IndexableFieldType
             {
                 get { return GetRealValue().IndexableFieldType; }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Suggest/Suggest/DocumentDictionary.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Suggest/Suggest/DocumentDictionary.cs b/src/Lucene.Net.Suggest/Suggest/DocumentDictionary.cs
index af9fabe..bc1b5b3 100644
--- a/src/Lucene.Net.Suggest/Suggest/DocumentDictionary.cs
+++ b/src/Lucene.Net.Suggest/Suggest/DocumentDictionary.cs
@@ -230,9 +230,7 @@ namespace Lucene.Net.Search.Suggest
                 IIndexableField weight = doc.GetField(outerInstance.weightField);
                 if (weight != null) // found weight as stored
                 {
-                    // LUCENENET TODO: See if we can make NumericValue into Decimal (which can be converted to any other type of number)
-                    // rather than using object.
-                    return (weight.GetNumericValue() != null) ? Convert.ToInt64(weight.GetNumericValue()) : 0;
+                    return weight.GetInt64ValueOrDefault();
                 } // found weight as NumericDocValue
                 else if (weightValues != null)
                 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWStoredFieldsWriter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWStoredFieldsWriter.cs b/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWStoredFieldsWriter.cs
index 22ccdf0..5e37f25 100644
--- a/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWStoredFieldsWriter.cs
+++ b/src/Lucene.Net.TestFramework/Codecs/Lucene3x/PreFlexRWStoredFieldsWriter.cs
@@ -117,28 +117,31 @@ namespace Lucene.Net.Codecs.Lucene3x
             // specific encodings for different fields?  and apps
             // can customize...
 
-            object number = field.GetNumericValue();
-            if (number != null)
+            // LUCENENET specific - To avoid boxing/unboxing, we don't
+            // call GetNumericValue(). Instead, we check the field type and then
+            // call the appropriate conversion method. 
+            Type numericType = field.GetNumericType();
+            if (numericType != null)
             {
-                if (number is sbyte? || number is short? || number is int?)
+                if (typeof(byte).Equals(numericType) || typeof(short).Equals(numericType) || typeof(int).Equals(numericType))
                 {
                     bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_INT;
                 }
-                else if (number is long?)
+                else if (typeof(long).Equals(numericType))
                 {
                     bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_LONG;
                 }
-                else if (number is float?)
+                else if (typeof(float).Equals(numericType))
                 {
                     bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_FLOAT;
                 }
-                else if (number is double?)
+                else if (typeof(double).Equals(numericType))
                 {
                     bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_DOUBLE;
                 }
                 else
                 {
-                    throw new System.ArgumentException("cannot store numeric type " + number.GetType());
+                    throw new System.ArgumentException("cannot store numeric type " + numericType);
                 }
                 @string = null;
                 bytes = null;
@@ -174,21 +177,21 @@ namespace Lucene.Net.Codecs.Lucene3x
             }
             else
             {
-                if (number is sbyte? || number is short? || number is int?)
+                if (typeof(byte).Equals(numericType) || typeof(short).Equals(numericType) || typeof(int).Equals(numericType))
                 {
-                    FieldsStream.WriteInt32((int)number);
+                    FieldsStream.WriteInt32(field.GetInt32Value().Value);
                 }
-                else if (number is long?)
+                else if (typeof(long).Equals(numericType))
                 {
-                    FieldsStream.WriteInt64((long)number);
+                    FieldsStream.WriteInt64(field.GetInt64Value().Value);
                 }
-                else if (number is float?)
+                else if (typeof(float).Equals(numericType))
                 {
-                    FieldsStream.WriteInt32(Number.SingleToInt32Bits((float)number));
+                    FieldsStream.WriteInt32(Number.SingleToInt32Bits(field.GetSingleValue().Value));
                 }
-                else if (number is double?)
+                else if (typeof(double).Equals(numericType))
                 {
-                    FieldsStream.WriteInt64(BitConverter.DoubleToInt64Bits((double)number));
+                    FieldsStream.WriteInt64(BitConverter.DoubleToInt64Bits(field.GetDoubleValue().Value));
                 }
                 else
                 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs b/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
index 6ba93de..9cde4c7 100644
--- a/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Index/BaseStoredFieldsFormatTestCase.cs
@@ -335,9 +335,11 @@ namespace Lucene.Net.Index
                 for (int docID = 0; docID < sub.NumDocs; docID++)
                 {
                     Document doc = sub.Document(docID);
-                    Field f = (Field)doc.GetField("nf");
+                    Field f = doc.GetField<Field>("nf");
                     Assert.IsTrue(f is StoredField, "got f=" + f);
+#pragma warning disable 612, 618
                     Assert.AreEqual(answers[ids.Get(docID)], f.GetNumericValue());
+#pragma warning restore 612, 618
                 }
             }
             r.Dispose();
@@ -410,7 +412,9 @@ namespace Lucene.Net.Index
                 }
                 else
                 {
+#pragma warning disable 612, 618
                     Assert.AreEqual(fld.GetNumericValue(), sField.GetNumericValue());
+#pragma warning restore 612, 618
                 }
             }
             reader.Dispose();
@@ -647,7 +651,7 @@ namespace Lucene.Net.Index
                     continue;
                 }
                 ++numDocs;
-                int docId = (int)doc.GetField("id").GetNumericValue();
+                int docId = (int)doc.GetField("id").GetInt32Value();
                 Assert.AreEqual(data[docId].Length + 1, doc.Fields.Count);
                 for (int j = 0; j < data[docId].Length; ++j)
                 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs b/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs
index 74f9c8e..2dad203 100644
--- a/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs
+++ b/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs
@@ -2410,7 +2410,9 @@ namespace Lucene.Net.Util
             Assert.AreEqual(leftField.Name, rightField.Name, info);
             Assert.AreEqual(leftField.GetBinaryValue(), rightField.GetBinaryValue(), info);
             Assert.AreEqual(leftField.GetStringValue(), rightField.GetStringValue(), info);
+#pragma warning disable 612, 618
             Assert.AreEqual(leftField.GetNumericValue(), rightField.GetNumericValue(), info);
+#pragma warning restore 612, 618
             // TODO: should we check the FT at all?
         }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.TestFramework/Util/TestUtil.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Util/TestUtil.cs b/src/Lucene.Net.TestFramework/Util/TestUtil.cs
index cec067e..62e2267 100644
--- a/src/Lucene.Net.TestFramework/Util/TestUtil.cs
+++ b/src/Lucene.Net.TestFramework/Util/TestUtil.cs
@@ -1058,7 +1058,7 @@ namespace Lucene.Net.Util
                     switch (dvType)
                     {
                         case DocValuesType.NUMERIC:
-                            field2 = new NumericDocValuesField(field1.Name, (long)field1.GetNumericValue());
+                            field2 = new NumericDocValuesField(field1.Name, field1.GetInt64Value().Value);
                             break;
 
                         case DocValuesType.BINARY:
@@ -1078,19 +1078,19 @@ namespace Lucene.Net.Util
                     switch (numType)
                     {
                         case NumericType.INT32:
-                            field2 = new Int32Field(field1.Name, (int)field1.GetNumericValue(), field1.FieldType);
+                            field2 = new Int32Field(field1.Name, field1.GetInt32Value().Value, field1.FieldType);
                             break;
 
                         case NumericType.SINGLE:
-                            field2 = new SingleField(field1.Name, (int)field1.GetNumericValue(), field1.FieldType);
+                            field2 = new SingleField(field1.Name, field1.GetInt32Value().Value, field1.FieldType);
                             break;
 
                         case NumericType.INT64:
-                            field2 = new Int64Field(field1.Name, (int)field1.GetNumericValue(), field1.FieldType);
+                            field2 = new Int64Field(field1.Name, field1.GetInt32Value().Value, field1.FieldType);
                             break;
 
                         case NumericType.DOUBLE:
-                            field2 = new DoubleField(field1.Name, (int)field1.GetNumericValue(), field1.FieldType);
+                            field2 = new DoubleField(field1.Name, field1.GetInt32Value().Value, field1.FieldType);
                             break;
 
                         default:

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests.Highlighter/Highlight/HighlighterTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Highlighter/Highlight/HighlighterTest.cs b/src/Lucene.Net.Tests.Highlighter/Highlight/HighlighterTest.cs
index c7be3a5..03abf65 100644
--- a/src/Lucene.Net.Tests.Highlighter/Highlight/HighlighterTest.cs
+++ b/src/Lucene.Net.Tests.Highlighter/Highlight/HighlighterTest.cs
@@ -11,6 +11,7 @@ using Lucene.Net.Util.Automaton;
 using NUnit.Framework;
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Text;
 using System.Xml;
@@ -512,7 +513,7 @@ namespace Lucene.Net.Search.Highlight
 
             for (int i = 0; i < hits.TotalHits; i++)
             {
-                String text = searcher.Doc(hits.ScoreDocs[i].Doc).GetField(NUMERIC_FIELD_NAME).GetNumericValue().toString();
+                String text = searcher.Doc(hits.ScoreDocs[i].Doc).GetField(NUMERIC_FIELD_NAME).GetStringValue(CultureInfo.InvariantCulture);
                 TokenStream tokenStream = analyzer.GetTokenStream(FIELD_NAME, text);
 
                 highlighter.TextFragmenter = (new SimpleFragmenter(40));

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Join/TestBlockJoin.cs b/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
index c28b350..bcd884b 100644
--- a/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
+++ b/src/Lucene.Net.Tests.Join/TestBlockJoin.cs
@@ -207,7 +207,7 @@ namespace Lucene.Net.Tests.Join
             childDoc = s.Doc(hits.ScoreDocs[0].Doc);
             //System.out.println("CHILD = " + childDoc + " docID=" + hits.ScoreDocs[0].Doc);
             assertEquals("java", childDoc.Get("skill"));
-            assertEquals(2007, childDoc.GetField("year").GetNumericValue());
+            assertEquals(2007, childDoc.GetField("year").GetInt32ValueOrDefault());
             assertEquals("Lisa", GetParentDoc(r, parentsFilter, hits.ScoreDocs[0].Doc).Get("name"));
 
             // Test with filter on child docs:

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests.Spatial/SpatialExample.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Spatial/SpatialExample.cs b/src/Lucene.Net.Tests.Spatial/SpatialExample.cs
index b60525b..c6f7c45 100644
--- a/src/Lucene.Net.Tests.Spatial/SpatialExample.cs
+++ b/src/Lucene.Net.Tests.Spatial/SpatialExample.cs
@@ -190,7 +190,7 @@ namespace Lucene.Net.Spatial
             gotIds = new int[docs.TotalHits];
             for (int i = 0; i < gotIds.Length; i++)
             {
-                gotIds[i] = Convert.ToInt32(indexSearcher.Doc(docs.ScoreDocs[i].Doc).GetField("id").GetNumericValue(), CultureInfo.InvariantCulture);
+                gotIds[i] = indexSearcher.Doc(docs.ScoreDocs[i].Doc).GetField("id").GetInt32Value().Value;
             }
             assertArrayEquals(ids, gotIds);
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests.Suggest/Suggest/DocumentDictionaryTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Suggest/Suggest/DocumentDictionaryTest.cs b/src/Lucene.Net.Tests.Suggest/Suggest/DocumentDictionaryTest.cs
index bdab9f8..8e34052 100644
--- a/src/Lucene.Net.Tests.Suggest/Suggest/DocumentDictionaryTest.cs
+++ b/src/Lucene.Net.Tests.Suggest/Suggest/DocumentDictionaryTest.cs
@@ -160,7 +160,7 @@ namespace Lucene.Net.Search.Suggest
                 //Document doc = docs.Remove(f.Utf8ToString());
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 IIndexableField weightField = doc.GetField(WEIGHT_FIELD_NAME);
-                assertEquals(inputIterator.Weight, (weightField != null) ? Convert.ToInt64(weightField.GetNumericValue()) : 0);
+                assertEquals(inputIterator.Weight, (weightField != null) ? weightField.GetInt64ValueOrDefault() : 0);
                 assertTrue(inputIterator.Payload.Equals(doc.GetField(PAYLOAD_FIELD_NAME).GetBinaryValue()));
             }
 
@@ -203,7 +203,7 @@ namespace Lucene.Net.Search.Suggest
                 docs.Remove(field);
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 IIndexableField weightField = doc.GetField(WEIGHT_FIELD_NAME);
-                assertEquals(inputIterator.Weight, (weightField != null) ? Convert.ToInt64(weightField.GetNumericValue()) : 0);
+                assertEquals(inputIterator.Weight, (weightField != null) ? weightField.GetInt64ValueOrDefault() : 0);
                 assertEquals(inputIterator.Payload, null);
             }
 
@@ -249,7 +249,7 @@ namespace Lucene.Net.Search.Suggest
                 //Document doc = docs.remove(f.utf8ToString());
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 IIndexableField weightField = doc.GetField(WEIGHT_FIELD_NAME);
-                assertEquals(inputIterator.Weight, (weightField != null) ? Convert.ToInt64(weightField.GetNumericValue()) : 0);
+                assertEquals(inputIterator.Weight, (weightField != null) ? weightField.GetInt64ValueOrDefault() : 0);
                 assertTrue(inputIterator.Payload.equals(doc.GetField(PAYLOAD_FIELD_NAME).GetBinaryValue()));
                 ISet<BytesRef> oriCtxs = new HashSet<BytesRef>();
                 IEnumerable<BytesRef> contextSet = inputIterator.Contexts;
@@ -327,7 +327,7 @@ namespace Lucene.Net.Search.Suggest
                 docs.Remove(field);
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 IIndexableField weightField = doc.GetField(WEIGHT_FIELD_NAME);
-                assertEquals(inputIterator.Weight, (weightField != null) ? Convert.ToInt64(weightField.GetNumericValue()) : 0);
+                assertEquals(inputIterator.Weight, (weightField != null) ? weightField.GetInt64ValueOrDefault() : 0);
                 assertEquals(inputIterator.Payload, null);
             }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests.Suggest/Suggest/DocumentValueSourceDictionaryTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Suggest/Suggest/DocumentValueSourceDictionaryTest.cs b/src/Lucene.Net.Tests.Suggest/Suggest/DocumentValueSourceDictionaryTest.cs
index 654089f..818e9d5 100644
--- a/src/Lucene.Net.Tests.Suggest/Suggest/DocumentValueSourceDictionaryTest.cs
+++ b/src/Lucene.Net.Tests.Suggest/Suggest/DocumentValueSourceDictionaryTest.cs
@@ -117,9 +117,9 @@ namespace Lucene.Net.Search.Suggest
                 Document doc = docs.ContainsKey(field) ? docs[field] : null;
                 docs.Remove(field);
                 //Document doc = docs.remove(f.utf8ToString());
-                long w1 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_1).GetNumericValue());
-                long w2 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_2).GetNumericValue());
-                long w3 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_3).GetNumericValue());
+                long w1 = doc.GetField(WEIGHT_FIELD_NAME_1).GetInt64ValueOrDefault();
+                long w2 = doc.GetField(WEIGHT_FIELD_NAME_2).GetInt64ValueOrDefault();
+                long w3 = doc.GetField(WEIGHT_FIELD_NAME_3).GetInt64ValueOrDefault();
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 assertEquals(inputIterator.Weight, (w1 + w2 + w3));
                 assertTrue(inputIterator.Payload.equals(doc.GetField(PAYLOAD_FIELD_NAME).GetBinaryValue()));
@@ -154,9 +154,9 @@ namespace Lucene.Net.Search.Suggest
                 string field = f.Utf8ToString();
                 Document doc = docs.ContainsKey(field) ? docs[field] : null;
                 docs.Remove(field);
-                long w1 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_1).GetNumericValue());
-                long w2 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_2).GetNumericValue());
-                long w3 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_3).GetNumericValue());
+                long w1 = doc.GetField(WEIGHT_FIELD_NAME_1).GetInt64ValueOrDefault();
+                long w2 = doc.GetField(WEIGHT_FIELD_NAME_2).GetInt64ValueOrDefault();
+                long w3 = doc.GetField(WEIGHT_FIELD_NAME_3).GetInt64ValueOrDefault();
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 assertEquals(inputIterator.Weight, (w1 + w2 + w3));
                 assertTrue(inputIterator.Payload.equals(doc.GetField(PAYLOAD_FIELD_NAME).GetBinaryValue()));
@@ -197,9 +197,9 @@ namespace Lucene.Net.Search.Suggest
                 string field = f.Utf8ToString();
                 Document doc = docs.ContainsKey(field) ? docs[field] : null;
                 docs.Remove(field);
-                long w1 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_1).GetNumericValue());
-                long w2 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_2).GetNumericValue());
-                long w3 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_3).GetNumericValue());
+                long w1 = doc.GetField(WEIGHT_FIELD_NAME_1).GetInt64ValueOrDefault();
+                long w2 = doc.GetField(WEIGHT_FIELD_NAME_2).GetInt64ValueOrDefault();
+                long w3 = doc.GetField(WEIGHT_FIELD_NAME_3).GetInt64ValueOrDefault();
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 assertEquals(inputIterator.Weight, (w1 + w2 + w3));
                 assertEquals(inputIterator.Payload, null);
@@ -262,8 +262,8 @@ namespace Lucene.Net.Search.Suggest
                 string field = f.Utf8ToString();
                 Document doc = docs.ContainsKey(field) ? docs[field] : null;
                 docs.Remove(field);
-                long w1 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_1).GetNumericValue());
-                long w2 = Convert.ToInt64(doc.GetField(WEIGHT_FIELD_NAME_2).GetNumericValue());
+                long w1 = doc.GetField(WEIGHT_FIELD_NAME_1).GetInt64ValueOrDefault();
+                long w2 = doc.GetField(WEIGHT_FIELD_NAME_2).GetInt64ValueOrDefault();
                 assertTrue(f.equals(new BytesRef(doc.Get(FIELD_NAME))));
                 assertEquals(inputIterator.Weight, w2 + w1);
                 assertTrue(inputIterator.Payload.equals(doc.GetField(PAYLOAD_FIELD_NAME).GetBinaryValue()));

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests/Document/TestField.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Document/TestField.cs b/src/Lucene.Net.Tests/Document/TestField.cs
index f436364..9ee7f30 100644
--- a/src/Lucene.Net.Tests/Document/TestField.cs
+++ b/src/Lucene.Net.Tests/Document/TestField.cs
@@ -52,7 +52,7 @@ namespace Lucene.Net.Documents
                 TrySetStringValue(field);
                 TrySetTokenStreamValue(field);
 
-                Assert.AreEqual(6d, (double)field.GetNumericValue(), 0.0d);
+                Assert.AreEqual(6d, field.GetDoubleValue().Value, 0.0d);
             }
         }
 
@@ -74,7 +74,7 @@ namespace Lucene.Net.Documents
             TrySetStringValue(field);
             TrySetTokenStreamValue(field);
 
-            Assert.AreEqual(6d, BitConverter.Int64BitsToDouble((long)field.GetNumericValue()), 0.0d);
+            Assert.AreEqual(6d, BitConverter.Int64BitsToDouble(field.GetInt64Value().Value), 0.0d);
         }
 
         [Test]
@@ -95,7 +95,7 @@ namespace Lucene.Net.Documents
             TrySetStringValue(field);
             TrySetTokenStreamValue(field);
 
-            Assert.AreEqual(6f, Number.Int32BitsToSingle(Convert.ToInt32(field.GetNumericValue())), 0.0f);
+            Assert.AreEqual(6f, Number.Int32BitsToSingle(field.GetInt32Value().Value), 0.0f);
         }
 
         [Test]
@@ -118,7 +118,7 @@ namespace Lucene.Net.Documents
                 TrySetStringValue(field);
                 TrySetTokenStreamValue(field);
 
-                Assert.AreEqual(6f, (float)field.GetNumericValue(), 0.0f);
+                Assert.AreEqual(6f, field.GetSingleValue().Value, 0.0f);
             }
         }
 
@@ -142,7 +142,7 @@ namespace Lucene.Net.Documents
                 TrySetStringValue(field);
                 TrySetTokenStreamValue(field);
 
-                Assert.AreEqual(6, (int)field.GetNumericValue());
+                Assert.AreEqual(6, field.GetInt32Value().Value);
             }
         }
 
@@ -164,7 +164,7 @@ namespace Lucene.Net.Documents
             TrySetStringValue(field);
             TrySetTokenStreamValue(field);
 
-            Assert.AreEqual(6L, (long)field.GetNumericValue());
+            Assert.AreEqual(6L, field.GetInt64Value().Value);
         }
 
         [Test]
@@ -187,7 +187,7 @@ namespace Lucene.Net.Documents
                 TrySetStringValue(field);
                 TrySetTokenStreamValue(field);
 
-                Assert.AreEqual(6L, (long)field.GetNumericValue());
+                Assert.AreEqual(6L, field.GetInt64Value().Value);
             }
         }
 
@@ -371,7 +371,7 @@ namespace Lucene.Net.Documents
             TrySetStringValue(field);
             TrySetTokenStreamValue(field);
 
-            Assert.AreEqual(5, (int)field.GetNumericValue());
+            Assert.AreEqual(5, field.GetInt32Value());
         }
 
         [Test]
@@ -391,7 +391,7 @@ namespace Lucene.Net.Documents
             TrySetStringValue(field);
             TrySetTokenStreamValue(field);
 
-            Assert.AreEqual(5D, (double)field.GetNumericValue(), 0.0D);
+            Assert.AreEqual(5D, field.GetDoubleValue().Value, 0.0D);
         }
 
         [Test]
@@ -411,7 +411,7 @@ namespace Lucene.Net.Documents
             TrySetStringValue(field);
             TrySetTokenStreamValue(field);
 
-            Assert.AreEqual(5f, (float)field.GetNumericValue(), 0.0f);
+            Assert.AreEqual(5f, field.GetSingleValue().Value, 0.0f);
         }
 
         [Test]
@@ -431,7 +431,7 @@ namespace Lucene.Net.Documents
             TrySetStringValue(field);
             TrySetTokenStreamValue(field);
 
-            Assert.AreEqual(5L, (long)field.GetNumericValue());
+            Assert.AreEqual(5L, field.GetInt64Value().Value);
         }
 
         private void TrySetByteValue(Field f)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs b/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs
index 4d557e1..71cc38a 100644
--- a/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs
+++ b/src/Lucene.Net.Tests/Index/TestIndexWriterExceptions.cs
@@ -2021,6 +2021,24 @@ namespace Lucene.Net.Index
                 return "baz";
             }
 
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified provider
+            public virtual string GetStringValue(IFormatProvider provider)
+            {
+                return GetStringValue();
+            }
+
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified format
+            public virtual string GetStringValue(string format)
+            {
+                return GetStringValue();
+            }
+
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified format and provider
+            public virtual string GetStringValue(string format, IFormatProvider provider)
+            {
+                return GetStringValue();
+            }
+
             public TextReader GetReaderValue()
             {
                 return null;
@@ -2031,6 +2049,13 @@ namespace Lucene.Net.Index
                 return null;
             }
 
+            // LUCENENET specific - Since we have no numeric reference types in .NET, this method was added to check
+            // the numeric type of the inner field without boxing/unboxing.
+            public virtual Type GetNumericType()
+            {
+                return null;
+            }
+
             // LUCENENET specific - created overload for Byte, since we have no Number class in .NET
             public virtual byte? GetByteValue()
             {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests/Index/TestIndexableField.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Index/TestIndexableField.cs b/src/Lucene.Net.Tests/Index/TestIndexableField.cs
index 2aac045..4be2e2e 100644
--- a/src/Lucene.Net.Tests/Index/TestIndexableField.cs
+++ b/src/Lucene.Net.Tests/Index/TestIndexableField.cs
@@ -178,6 +178,24 @@ namespace Lucene.Net.Index
                 }
             }
 
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified provider
+            public virtual string GetStringValue(IFormatProvider provider)
+            {
+                return GetStringValue();
+            }
+
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified format
+            public virtual string GetStringValue(string format)
+            {
+                return GetStringValue();
+            }
+
+            // LUCENENET specific - created overload so we can format an underlying numeric type using specified format and provider
+            public virtual string GetStringValue(string format, IFormatProvider provider)
+            {
+                return GetStringValue();
+            }
+
             public TextReader GetReaderValue()
             {
                 if (Counter % 10 == 7)
@@ -195,6 +213,13 @@ namespace Lucene.Net.Index
                 return null;
             }
 
+            // LUCENENET specific - Since we have no numeric reference types in .NET, this method was added to check
+            // the numeric type of the inner field without boxing/unboxing.
+            public virtual Type GetNumericType()
+            {
+                return null;
+            }
+
             // LUCENENET specific - created overload for Byte, since we have no Number class in .NET
             public virtual byte? GetByteValue()
             {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests/Search/TestLiveFieldValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/TestLiveFieldValues.cs b/src/Lucene.Net.Tests/Search/TestLiveFieldValues.cs
index bdf3ecf..5a5b8c1 100644
--- a/src/Lucene.Net.Tests/Search/TestLiveFieldValues.cs
+++ b/src/Lucene.Net.Tests/Search/TestLiveFieldValues.cs
@@ -124,7 +124,7 @@ namespace Lucene.Net.Search
                 else
                 {
                     Document doc = s.Doc(hits.ScoreDocs[0].Doc);
-                    return (int)doc.GetField("field").GetNumericValue();
+                    return doc.GetField("field").GetInt32Value();
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests/Search/TestNumericRangeQuery32.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/TestNumericRangeQuery32.cs b/src/Lucene.Net.Tests/Search/TestNumericRangeQuery32.cs
index 6d73ab5..ebf23f2 100644
--- a/src/Lucene.Net.Tests/Search/TestNumericRangeQuery32.cs
+++ b/src/Lucene.Net.Tests/Search/TestNumericRangeQuery32.cs
@@ -195,9 +195,9 @@ namespace Lucene.Net.Search
                 Assert.IsNotNull(sd);
                 Assert.AreEqual(count, sd.Length, "Score doc count" + type);
                 Document doc = Searcher.Doc(sd[0].Doc);
-                Assert.AreEqual(2 * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "First doc" + type);
+                Assert.AreEqual(2 * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "First doc" + type);
                 doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-                Assert.AreEqual((1 + count) * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "Last doc" + type);
+                Assert.AreEqual((1 + count) * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "Last doc" + type);
             }
         }
 
@@ -252,9 +252,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(count, sd.Length, "Score doc count");
             Document doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(StartOffset, (int)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(StartOffset, doc.GetField(field).GetInt32Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((count - 1) * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((count - 1) * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "Last doc");
 
             q = NumericRangeQuery.NewInt32Range(field, precisionStep, null, upper, false, true);
             topDocs = Searcher.Search(q, null, NoDocs, Sort.INDEXORDER);
@@ -262,9 +262,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(count, sd.Length, "Score doc count");
             doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(StartOffset, (int)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(StartOffset, doc.GetField(field).GetInt32Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((count - 1) * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((count - 1) * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "Last doc");
         }
 
         [Test]
@@ -296,9 +296,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(NoDocs - count, sd.Length, "Score doc count");
             Document doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(count * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(count * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "Last doc");
 
             q = NumericRangeQuery.NewInt32Range(field, precisionStep, lower, null, true, false);
             topDocs = Searcher.Search(q, null, NoDocs, Sort.INDEXORDER);
@@ -306,9 +306,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(NoDocs - count, sd.Length, "Score doc count");
             doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(count * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(count * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, (int)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, doc.GetField(field).GetInt32Value().Value, "Last doc");
         }
 
         [Test]
@@ -654,10 +654,10 @@ namespace Lucene.Net.Search
                 }
                 ScoreDoc[] sd = topDocs.ScoreDocs;
                 Assert.IsNotNull(sd);
-                int last = (int)Searcher.Doc(sd[0].Doc).GetField(field).GetNumericValue();
+                int last = Searcher.Doc(sd[0].Doc).GetField(field).GetInt32Value().Value;
                 for (int j = 1; j < sd.Length; j++)
                 {
-                    int act = (int)Searcher.Doc(sd[j].Doc).GetField(field).GetNumericValue();
+                    int act = Searcher.Doc(sd[j].Doc).GetField(field).GetInt32Value().Value;
                     Assert.IsTrue(last > act, "Docs should be sorted backwards");
                     last = act;
                 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net.Tests/Search/TestNumericRangeQuery64.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Search/TestNumericRangeQuery64.cs b/src/Lucene.Net.Tests/Search/TestNumericRangeQuery64.cs
index f26f35c..aeed164 100644
--- a/src/Lucene.Net.Tests/Search/TestNumericRangeQuery64.cs
+++ b/src/Lucene.Net.Tests/Search/TestNumericRangeQuery64.cs
@@ -205,9 +205,9 @@ namespace Lucene.Net.Search
                 Assert.IsNotNull(sd);
                 Assert.AreEqual(count, sd.Length, "Score doc count" + type);
                 Document doc = Searcher.Doc(sd[0].Doc);
-                Assert.AreEqual(2 * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "First doc" + type);
+                Assert.AreEqual(2 * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "First doc" + type);
                 doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-                Assert.AreEqual((1 + count) * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "Last doc" + type);
+                Assert.AreEqual((1 + count) * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "Last doc" + type);
             }
         }
 
@@ -268,9 +268,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(count, sd.Length, "Score doc count");
             Document doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(StartOffset, (long)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(StartOffset, doc.GetField(field).GetInt64Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((count - 1) * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((count - 1) * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "Last doc");
 
             q = NumericRangeQuery.NewInt64Range(field, precisionStep, null, upper, false, true);
             topDocs = Searcher.Search(q, null, NoDocs, Sort.INDEXORDER);
@@ -278,9 +278,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(count, sd.Length, "Score doc count");
             doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(StartOffset, (long)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(StartOffset, doc.GetField(field).GetInt64Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((count - 1) * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((count - 1) * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "Last doc");
         }
 
         [Test]
@@ -318,9 +318,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(NoDocs - count, sd.Length, "Score doc count");
             Document doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(count * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(count * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "Last doc");
 
             q = NumericRangeQuery.NewInt64Range(field, precisionStep, lower, null, true, false);
             topDocs = Searcher.Search(q, null, NoDocs, Sort.INDEXORDER);
@@ -328,9 +328,9 @@ namespace Lucene.Net.Search
             Assert.IsNotNull(sd);
             Assert.AreEqual(NoDocs - count, sd.Length, "Score doc count");
             doc = Searcher.Doc(sd[0].Doc);
-            Assert.AreEqual(count * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "First doc");
+            Assert.AreEqual(count * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "First doc");
             doc = Searcher.Doc(sd[sd.Length - 1].Doc);
-            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, (long)doc.GetField(field).GetNumericValue(), "Last doc");
+            Assert.AreEqual((NoDocs - 1) * Distance + StartOffset, doc.GetField(field).GetInt64Value().Value, "Last doc");
         }
 
         [Test]
@@ -700,10 +700,10 @@ namespace Lucene.Net.Search
                 }
                 ScoreDoc[] sd = topDocs.ScoreDocs;
                 Assert.IsNotNull(sd);
-                long last = (long)Searcher.Doc(sd[0].Doc).GetField(field).GetNumericValue();
+                long last = Searcher.Doc(sd[0].Doc).GetField(field).GetInt64Value().Value;
                 for (int j = 1; j < sd.Length; j++)
                 {
-                    long act = (long)Searcher.Doc(sd[j].Doc).GetField(field).GetNumericValue();
+                    long act = Searcher.Doc(sd[j].Doc).GetField(field).GetInt64Value().Value;
                     Assert.IsTrue(last > act, "Docs should be sorted backwards");
                     last = act;
                 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net/Codecs/Compressing/CompressingStoredFieldsWriter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Codecs/Compressing/CompressingStoredFieldsWriter.cs b/src/Lucene.Net/Codecs/Compressing/CompressingStoredFieldsWriter.cs
index 879bb7a..6703e33 100644
--- a/src/Lucene.Net/Codecs/Compressing/CompressingStoredFieldsWriter.cs
+++ b/src/Lucene.Net/Codecs/Compressing/CompressingStoredFieldsWriter.cs
@@ -6,6 +6,7 @@ using Lucene.Net.Util;
 using Lucene.Net.Util.Packed;
 using System;
 using System.Diagnostics;
+using System.Globalization;
 using Document = Lucene.Net.Documents.Document;
 
 namespace Lucene.Net.Codecs.Compressing
@@ -269,61 +270,31 @@ namespace Lucene.Net.Codecs.Compressing
             BytesRef bytes;
             string @string;
 
-            object number = (object)field.GetNumericValue();
-            if (number != null)
+            // LUCENENET specific - To avoid boxing/unboxing, we don't
+            // call GetNumericValue(). Instead, we check the field type and then
+            // call the appropriate conversion method. 
+            Type numericType = field.GetNumericType();
+            if (numericType != null)
             {
-                if (number is string)
+                if (typeof(byte).Equals(numericType) || typeof(short).Equals(numericType) || typeof(int).Equals(numericType))
                 {
-                    string numStr = number.ToString();
-                    sbyte dummySbyte;
-                    short dummyShort;
-                    int dummyInt;
-                    long dummyLong;
-                    float dummyFloat;
-                    double dummyDouble;
-                    if (sbyte.TryParse(numStr, out dummySbyte) || short.TryParse(numStr, out dummyShort) || int.TryParse(numStr, out dummyInt))
-                    {
-                        bits = NUMERIC_INT32;
-                    }
-                    else if (long.TryParse(numStr, out dummyLong))
-                    {
-                        bits = NUMERIC_INT64;
-                    }
-                    else if (float.TryParse(numStr, out dummyFloat))
-                    {
-                        bits = NUMERIC_SINGLE;
-                    }
-                    else if (double.TryParse(numStr, out dummyDouble))
-                    {
-                        bits = NUMERIC_DOUBLE;
-                    }
-                    else
-                    {
-                        throw new System.ArgumentException("cannot store numeric type " + number.GetType());
-                    }
+                    bits = NUMERIC_INT32;
+                }
+                else if (typeof(long).Equals(numericType))
+                {
+                    bits = NUMERIC_INT64;
+                }
+                else if (typeof(float).Equals(numericType))
+                {
+                    bits = NUMERIC_SINGLE;
+                }
+                else if (typeof(double).Equals(numericType))
+                {
+                    bits = NUMERIC_DOUBLE;
                 }
                 else
                 {
-                    if (number is sbyte || number is short || number is int)
-                    {
-                        bits = NUMERIC_INT32;
-                    }
-                    else if (number is long)
-                    {
-                        bits = NUMERIC_INT64;
-                    }
-                    else if (number is float)
-                    {
-                        bits = NUMERIC_SINGLE;
-                    }
-                    else if (number is double)
-                    {
-                        bits = NUMERIC_DOUBLE;
-                    }
-                    else
-                    {
-                        throw new System.ArgumentException("cannot store numeric type " + number.GetType());
-                    }
+                    throw new System.ArgumentException("cannot store numeric type " + numericType);
                 }
 
                 @string = null;
@@ -343,7 +314,7 @@ namespace Lucene.Net.Codecs.Compressing
                     @string = field.GetStringValue();
                     if (@string == null)
                     {
-                        throw new System.ArgumentException("field " + field.Name + " is stored but does not have binaryValue, stringValue nor numericValue");
+                        throw new System.ArgumentException("field " + field.Name + " is stored but does not have BinaryValue, StringValue nor NumericValue");
                     }
                 }
             }
@@ -362,59 +333,25 @@ namespace Lucene.Net.Codecs.Compressing
             }
             else
             {
-                if (number is string)
+                if (typeof(byte).Equals(numericType) || typeof(short).Equals(numericType) || typeof(int).Equals(numericType))
                 {
-                    string numStr = number.ToString();
-                    sbyte dummySbyte;
-                    short dummyShort;
-                    int dummyInt;
-                    long dummyLong;
-                    float dummyFloat;
-                    double dummyDouble;
-                    if (sbyte.TryParse(numStr, out dummySbyte) || short.TryParse(numStr, out dummyShort) ||
-                        int.TryParse(numStr, out dummyInt))
-                    {
-                        bits = NUMERIC_INT32;
-                    }
-                    else if (long.TryParse(numStr, out dummyLong))
-                    {
-                        bits = NUMERIC_INT64;
-                    }
-                    else if (float.TryParse(numStr, out dummyFloat))
-                    {
-                        bits = NUMERIC_SINGLE;
-                    }
-                    else if (double.TryParse(numStr, out dummyDouble))
-                    {
-                        bits = NUMERIC_DOUBLE;
-                    }
-                    else
-                    {
-                        throw new System.ArgumentException("cannot store numeric type " + number.GetType());
-                    }
+                    bufferedDocs.WriteInt32(field.GetInt32Value().Value);
+                }
+                else if (typeof(long).Equals(numericType))
+                {
+                    bufferedDocs.WriteInt64(field.GetInt64Value().Value);
+                }
+                else if (typeof(float).Equals(numericType))
+                {
+                    bufferedDocs.WriteInt32(Number.SingleToInt32Bits(field.GetSingleValue().Value));
+                }
+                else if (typeof(double).Equals(numericType))
+                {
+                    bufferedDocs.WriteInt64(BitConverter.DoubleToInt64Bits(field.GetDoubleValue().Value));
                 }
                 else
                 {
-                    if (number is sbyte || number is short || number is int)
-                    {
-                        bufferedDocs.WriteInt32((int)number);
-                    }
-                    else if (number is long)
-                    {
-                        bufferedDocs.WriteInt64((long)number);
-                    }
-                    else if (number is float)
-                    {
-                        bufferedDocs.WriteInt32(Number.SingleToInt32Bits((float)number));
-                    }
-                    else if (number is double)
-                    {
-                        bufferedDocs.WriteInt64(BitConverter.DoubleToInt64Bits((double)number));
-                    }
-                    else
-                    {
-                        throw new Exception("Cannot get here");
-                    }
+                    throw new Exception("Cannot get here");
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net/Codecs/Lucene40/Lucene40StoredFieldsWriter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Codecs/Lucene40/Lucene40StoredFieldsWriter.cs b/src/Lucene.Net/Codecs/Lucene40/Lucene40StoredFieldsWriter.cs
index 44b680c..92a6e5f 100644
--- a/src/Lucene.Net/Codecs/Lucene40/Lucene40StoredFieldsWriter.cs
+++ b/src/Lucene.Net/Codecs/Lucene40/Lucene40StoredFieldsWriter.cs
@@ -161,28 +161,31 @@ namespace Lucene.Net.Codecs.Lucene40
             // specific encodings for different fields?  and apps
             // can customize...
 
-            object number = (object)field.GetNumericValue();
-            if (number != null)
+            // LUCENENET specific - To avoid boxing/unboxing, we don't
+            // call GetNumericValue(). Instead, we check the field type and then
+            // call the appropriate conversion method. 
+            Type numericType = field.GetNumericType();
+            if (numericType != null)
             {
-                if (number is sbyte || number is short || number is int)
+                if (typeof(byte).Equals(numericType) || typeof(short).Equals(numericType) || typeof(int).Equals(numericType))
                 {
                     bits |= FIELD_IS_NUMERIC_INT;
                 }
-                else if (number is long)
+                else if (typeof(long).Equals(numericType))
                 {
                     bits |= FIELD_IS_NUMERIC_LONG;
                 }
-                else if (number is float)
+                else if (typeof(float).Equals(numericType))
                 {
                     bits |= FIELD_IS_NUMERIC_FLOAT;
                 }
-                else if (number is double)
+                else if (typeof(double).Equals(numericType))
                 {
                     bits |= FIELD_IS_NUMERIC_DOUBLE;
                 }
                 else
                 {
-                    throw new System.ArgumentException("cannot store numeric type " + number.GetType());
+                    throw new System.ArgumentException("cannot store numeric type " + numericType);
                 }
                 @string = null;
                 bytes = null;
@@ -218,21 +221,21 @@ namespace Lucene.Net.Codecs.Lucene40
             }
             else
             {
-                if (number is sbyte || number is short || number is int)
+                if (typeof(byte).Equals(numericType) || typeof(short).Equals(numericType) || typeof(int).Equals(numericType))
                 {
-                    fieldsStream.WriteInt32((int)number);
+                    fieldsStream.WriteInt32(field.GetInt32Value().Value);
                 }
-                else if (number is long)
+                else if (typeof(long).Equals(numericType))
                 {
-                    fieldsStream.WriteInt64((long)number);
+                    fieldsStream.WriteInt64(field.GetInt64Value().Value);
                 }
-                else if (number is float)
+                else if (typeof(float).Equals(numericType))
                 {
-                    fieldsStream.WriteInt32(Number.SingleToInt32Bits((float)number));
+                    fieldsStream.WriteInt32(Number.SingleToInt32Bits(field.GetSingleValue().Value));
                 }
-                else if (number is double)
+                else if (typeof(double).Equals(numericType))
                 {
-                    fieldsStream.WriteInt64(BitConverter.DoubleToInt64Bits((double)number));
+                    fieldsStream.WriteInt64(BitConverter.DoubleToInt64Bits(field.GetDoubleValue().Value));
                 }
                 else
                 {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net/Document/Field.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Document/Field.cs b/src/Lucene.Net/Document/Field.cs
index 793b047..d7fea34 100644
--- a/src/Lucene.Net/Document/Field.cs
+++ b/src/Lucene.Net/Document/Field.cs
@@ -3,6 +3,7 @@ using Lucene.Net.Analysis.TokenAttributes;
 using Lucene.Net.Index;
 using Lucene.Net.Util;
 using System;
+using System.Globalization;
 using System.IO;
 using System.Text;
 
@@ -288,6 +289,7 @@ namespace Lucene.Net.Documents
         /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
         /// <see cref="GetBinaryValue()"/> must be set.
         /// </summary>
+        /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
         public virtual string GetStringValue() // LUCENENET specific: Added verb Get to make it more clear that this returns the value
         {
             if (m_fieldsData is string || m_fieldsData is Number)
@@ -305,7 +307,10 @@ namespace Lucene.Net.Documents
         /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
         /// <see cref="GetBinaryValue()"/> must be set.
         /// </summary>
-        public virtual string GetStringValue(IFormatProvider provider) // LUCENENET specific: Added verb Get to make it more clear that this returns the value
+        /// <param name="provider">An object that supplies culture-specific formatting information. This parameter has no effect if this field is non-numeric.</param>
+        /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
+        // LUCENENET specific overload.
+        public virtual string GetStringValue(IFormatProvider provider) 
         {
             if (m_fieldsData is string)
             {
@@ -321,7 +326,15 @@ namespace Lucene.Net.Documents
             }
         }
 
-        public virtual string GetStringValue(string format) // LUCENENET specific: Added verb Get to make it more clear that this returns the value
+        /// <summary>
+        /// The value of the field as a <see cref="string"/>, or <c>null</c>. If <c>null</c>, the <see cref="TextReader"/> value or
+        /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
+        /// <see cref="GetBinaryValue()"/> must be set.
+        /// </summary>
+        /// <param name="format">A standard or custom numeric format string. This parameter has no effect if this field is non-numeric.</param>
+        /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
+        // LUCENENET specific overload.
+        public virtual string GetStringValue(string format) 
         {
             if (m_fieldsData is string)
             {
@@ -337,7 +350,16 @@ namespace Lucene.Net.Documents
             }
         }
 
-        public virtual string GetStringValue(string format, IFormatProvider provider) // LUCENENET specific: Added verb Get to make it more clear that this returns the value
+        /// <summary>
+        /// The value of the field as a <see cref="string"/>, or <c>null</c>. If <c>null</c>, the <see cref="TextReader"/> value or
+        /// binary value is used. Exactly one of <see cref="GetStringValue()"/>, <see cref="GetReaderValue()"/>, and
+        /// <see cref="GetBinaryValue()"/> must be set.
+        /// </summary>
+        /// <param name="format">A standard or custom numeric format string. This parameter has no effect if this field is non-numeric.</param>
+        /// <param name="provider">An object that supplies culture-specific formatting information. This parameter has no effect if this field is non-numeric.</param>
+        /// <returns>The string representation of the value if it is either a <see cref="string"/> or numeric type.</returns>
+        // LUCENENET specific overload.
+        public virtual string GetStringValue(string format, IFormatProvider provider)
         {
             if (m_fieldsData is string)
             {
@@ -572,6 +594,7 @@ namespace Lucene.Net.Documents
             }
         }
 
+        [Obsolete("In .NET, use of this method will cause boxing/unboxing. Instead, call GetNumericType() to check the underlying type and call the appropriate GetXXXValue() method to retrieve the value.")]
         public virtual object GetNumericValue() // LUCENENET specific: Added verb Get to make it more clear that this returns the value
         {
             // LUCENENET NOTE: Originally, there was a conversion from string to a numeric value here.
@@ -608,6 +631,50 @@ namespace Lucene.Net.Documents
             return null;
         }
 
+        /// <summary>
+        /// Gets the <see cref="Type"/> of the underlying value, or <c>null</c> if the value is not set or non-numeric.
+        /// <para/>
+        /// LUCENENET specific. In Java, the numeric type was determined by checking the type of  
+        /// <see cref="GetNumericValue()"/>. However, since there are no reference number
+        /// types in .NET, using <see cref="GetNumericValue()"/> so will cause boxing/unboxing. It is
+        /// therefore recommended to call this method to check the underlying type and the corresponding 
+        /// <c>Get*Value()</c> method to retrieve the value.
+        /// </summary>
+        public virtual Type GetNumericType() 
+        {
+            if (m_fieldsData is Int32)
+            {
+                return typeof(int);
+            }
+            else if (m_fieldsData is Int64)
+            {
+                return typeof(long);
+            }
+            else if (m_fieldsData is Single)
+            {
+                return typeof(float);
+            }
+            else if (m_fieldsData is Double)
+            {
+                return typeof(double);
+            }
+            else if (m_fieldsData is Int16)
+            {
+                return typeof(short);
+            }
+            else if (m_fieldsData is Byte)
+            {
+                return typeof(byte);
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Returns the field value as <see cref="byte"/> or <c>null</c> if the type
+        /// is non-numeric.
+        /// </summary>
+        /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
         // LUCENENET specific - created overload for Byte, since we have no Number class in .NET
         public virtual byte? GetByteValue()
         {
@@ -621,6 +688,11 @@ namespace Lucene.Net.Documents
             }
         }
 
+        /// <summary>
+        /// Returns the field value as <see cref="short"/> or <c>null</c> if the type
+        /// is non-numeric.
+        /// </summary>
+        /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
         // LUCENENET specific - created overload for Short, since we have no Number class in .NET
         public virtual short? GetInt16Value()
         {
@@ -634,6 +706,11 @@ namespace Lucene.Net.Documents
             }
         }
 
+        /// <summary>
+        /// Returns the field value as <see cref="int"/> or <c>null</c> if the type
+        /// is non-numeric.
+        /// </summary>
+        /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
         // LUCENENET specific - created overload for Int32, since we have no Number class in .NET
         public virtual int? GetInt32Value()
         {
@@ -647,6 +724,11 @@ namespace Lucene.Net.Documents
             }
         }
 
+        /// <summary>
+        /// Returns the field value as <see cref="long"/> or <c>null</c> if the type
+        /// is non-numeric.
+        /// </summary>
+        /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
         // LUCENENET specific - created overload for Int64, since we have no Number class in .NET
         public virtual long? GetInt64Value()
         {
@@ -660,6 +742,11 @@ namespace Lucene.Net.Documents
             }
         }
 
+        /// <summary>
+        /// Returns the field value as <see cref="float"/> or <c>null</c> if the type
+        /// is non-numeric.
+        /// </summary>
+        /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
         // LUCENENET specific - created overload for Single, since we have no Number class in .NET
         public virtual float? GetSingleValue()
         {
@@ -673,6 +760,11 @@ namespace Lucene.Net.Documents
             }
         }
 
+        /// <summary>
+        /// Returns the field value as <see cref="double"/> or <c>null</c> if the type
+        /// is non-numeric.
+        /// </summary>
+        /// <returns>The field value or <c>null</c> if the type is non-numeric.</returns>
         // LUCENENET specific - created overload for Double, since we have no Number class in .NET
         public virtual double? GetDoubleValue()
         {
@@ -686,7 +778,8 @@ namespace Lucene.Net.Documents
             }
         }
 
-
+        /// <summary>
+        /// Non-null if this field has a binary value. </summary>
         public virtual BytesRef GetBinaryValue() // LUCENENET specific: Added verb Get to make it more clear that this returns the value
         {
             if (m_fieldsData is BytesRef)
@@ -728,7 +821,7 @@ namespace Lucene.Net.Documents
         }
 
         /// <summary>
-        /// Returns the <see cref="Documents.FieldType"/> for this field as type <see cref="IIndexableFieldType"/> </summary>
+        /// Returns the <see cref="Documents.FieldType"/> for this field as type <see cref="IIndexableFieldType"/>. </summary>
         public virtual IIndexableFieldType IndexableFieldType
         {
             get { return m_type; }
@@ -776,9 +869,14 @@ namespace Lucene.Net.Documents
                 return internalTokenStream;
             }
 
+            // LUCENENET specific - If the underlying type is numeric, we need
+            // to ensure it is setup to be round-tripped.
+            string format = (numericType == NumericType.SINGLE || numericType == NumericType.DOUBLE) ? "R" : null;
+            string stringValue = GetStringValue(format, CultureInfo.InvariantCulture);
+
             if (!IndexableFieldType.IsTokenized)
             {
-                if (GetStringValue() == null)
+                if (stringValue == null)
                 {
                     throw new System.ArgumentException("Non-Tokenized Fields must have a String value");
                 }
@@ -788,7 +886,7 @@ namespace Lucene.Net.Documents
                     // (attributes,...) if not needed (stored field loading)
                     internalTokenStream = new StringTokenStream();
                 }
-                ((StringTokenStream)internalTokenStream).SetValue(GetStringValue()); // LUCENENET TODO: API Make overload that accepts format/provider
+                ((StringTokenStream)internalTokenStream).SetValue(stringValue);
                 return internalTokenStream;
             }
 
@@ -800,9 +898,9 @@ namespace Lucene.Net.Documents
             {
                 return analyzer.GetTokenStream(Name, GetReaderValue());
             }
-            else if (GetStringValue() != null)
+            else if (stringValue != null)
             {
-                TextReader sr = new StringReader(GetStringValue()); // LUCENENET TODO: API Make overload that accepts format/provider
+                TextReader sr = new StringReader(stringValue);
                 return analyzer.GetTokenStream(Name, sr);
             }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c22ef079/src/Lucene.Net/Index/DocValuesProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Index/DocValuesProcessor.cs b/src/Lucene.Net/Index/DocValuesProcessor.cs
index 0e820f0..0c1835b 100644
--- a/src/Lucene.Net/Index/DocValuesProcessor.cs
+++ b/src/Lucene.Net/Index/DocValuesProcessor.cs
@@ -1,3 +1,4 @@
+using Lucene.Net.Documents;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -72,11 +73,12 @@ namespace Lucene.Net.Index
                 }
                 else if (dvType == DocValuesType.NUMERIC)
                 {
-                    if (!(field.GetNumericValue() is long?))
+                    Type numericType = field.GetNumericType();
+                    if (!(typeof(long).Equals(numericType)))
                     {
-                        throw new System.ArgumentException("illegal type " + field.GetNumericValue().GetType() + ": DocValues types must be Long");
+                        throw new System.ArgumentException("illegal type " + numericType + ": DocValues types must be " + typeof(long));
                     }
-                    AddNumericField(fieldInfo, docID, (long)field.GetNumericValue());
+                    AddNumericField(fieldInfo, docID, field.GetInt64ValueOrDefault());
                 }
                 else
                 {