C# Proto2 feature : Field presence and default values (#4642)

* Compiler changes

* Generated code changes

* Library changes

* Compiler style changes

* Generated style changes

* Fix Windows build errors

* Implement changes from review

* Reintroduce proto2 check

* Compiler changes (required handling review)

* Generated code changes (required handling review)

* Library changes (required handling review

* Field presence rewrite (compiler changes)

* Field presence rewrite (generated code changes)

* Compiler comment

* IFieldAccessor.HasValue library implementation

* Remove Clear methods and default values from proto3 code (Compiler)

* Remove Clear methods and default values from proto3 code (Generated)

* Remove Clear methods and default values from proto3 code (Library)

* Fix distcheck error

* Rewrite default string values to use base64 and convert

* Library changes (IMessage2)

* Compiler changes (IMessage2)

* Generated changes (IMessage2)

* Rebased and regenerated

* Compiler changes (initialized extension)

* Generated changes (initialized extension)

* Library changes (initialized extension)

* Refactor MessageExtensions.IsRequired

* Move string default value creator and bytes default value creator back to seperate methods

* Dead code cleanup

* Fixed segmentation fault
Removed unused header method declarations
diff --git a/Makefile.am b/Makefile.am
index c26c4c9..73c1e6f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -179,7 +179,6 @@
   csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs                   \
   csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs             \
   csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs                 \
-  csharp/src/Google.Protobuf/Reflection/PartialClasses.cs                    \
   csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs                    \
   csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs             \
   csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs                 \
diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs
index 21a8ce0..d3e1ea9 100644
--- a/csharp/src/AddressBook/Addressbook.cs
+++ b/csharp/src/AddressBook/Addressbook.cs
@@ -247,7 +247,7 @@
       phones_.Add(other.phones_);
       if (other.lastUpdated_ != null) {
         if (lastUpdated_ == null) {
-          lastUpdated_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+          LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp();
         }
         LastUpdated.MergeFrom(other.LastUpdated);
       }
@@ -280,9 +280,9 @@
           }
           case 42: {
             if (lastUpdated_ == null) {
-              lastUpdated_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+              LastUpdated = new global::Google.Protobuf.WellKnownTypes.Timestamp();
             }
-            input.ReadMessage(lastUpdated_);
+            input.ReadMessage(LastUpdated);
             break;
           }
         }
@@ -447,7 +447,7 @@
                 break;
               }
               case 16: {
-                type_ = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum();
+                Type = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum();
                 break;
               }
             }
diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
index 46793ce..cd9b77a 100644
--- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
@@ -354,7 +354,7 @@
             break;
           }
           case 24: {
-            requestedOutputFormat_ = (global::Conformance.WireFormat) input.ReadEnum();
+            RequestedOutputFormat = (global::Conformance.WireFormat) input.ReadEnum();
             break;
           }
           case 34: {
@@ -362,7 +362,7 @@
             break;
           }
           case 40: {
-            testCategory_ = (global::Conformance.TestCategory) input.ReadEnum();
+            TestCategory = (global::Conformance.TestCategory) input.ReadEnum();
             break;
           }
         }
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
index 51715a0..6d3cd02 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
@@ -724,7 +724,7 @@
       }
       if (other.testMap_ != null) {
         if (testMap_ == null) {
-          testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
+          TestMap = new global::Google.Protobuf.TestProtos.TestMap();
         }
         TestMap.MergeFrom(other.TestMap);
       }
@@ -741,9 +741,9 @@
             break;
           case 10: {
             if (testMap_ == null) {
-              testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
+              TestMap = new global::Google.Protobuf.TestProtos.TestMap();
             }
-            input.ReadMessage(testMap_);
+            input.ReadMessage(TestMap);
             break;
           }
         }
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
index 7353be7..d74422b 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
@@ -1171,6 +1171,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_int32_wrapper" field.</summary>
     public const int OptionalInt32WrapperFieldNumber = 202;
     private static readonly pb::FieldCodec<int?> _single_optionalInt32Wrapper_codec = pb::FieldCodec.ForStructWrapper<int>(1618);
@@ -1183,6 +1184,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_int64_wrapper" field.</summary>
     public const int OptionalInt64WrapperFieldNumber = 203;
     private static readonly pb::FieldCodec<long?> _single_optionalInt64Wrapper_codec = pb::FieldCodec.ForStructWrapper<long>(1626);
@@ -1195,6 +1197,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_uint32_wrapper" field.</summary>
     public const int OptionalUint32WrapperFieldNumber = 204;
     private static readonly pb::FieldCodec<uint?> _single_optionalUint32Wrapper_codec = pb::FieldCodec.ForStructWrapper<uint>(1634);
@@ -1207,6 +1210,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_uint64_wrapper" field.</summary>
     public const int OptionalUint64WrapperFieldNumber = 205;
     private static readonly pb::FieldCodec<ulong?> _single_optionalUint64Wrapper_codec = pb::FieldCodec.ForStructWrapper<ulong>(1642);
@@ -1219,6 +1223,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_float_wrapper" field.</summary>
     public const int OptionalFloatWrapperFieldNumber = 206;
     private static readonly pb::FieldCodec<float?> _single_optionalFloatWrapper_codec = pb::FieldCodec.ForStructWrapper<float>(1650);
@@ -1231,6 +1236,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_double_wrapper" field.</summary>
     public const int OptionalDoubleWrapperFieldNumber = 207;
     private static readonly pb::FieldCodec<double?> _single_optionalDoubleWrapper_codec = pb::FieldCodec.ForStructWrapper<double>(1658);
@@ -1243,6 +1249,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_string_wrapper" field.</summary>
     public const int OptionalStringWrapperFieldNumber = 208;
     private static readonly pb::FieldCodec<string> _single_optionalStringWrapper_codec = pb::FieldCodec.ForClassWrapper<string>(1666);
@@ -1255,6 +1262,7 @@
       }
     }
 
+
     /// <summary>Field number for the "optional_bytes_wrapper" field.</summary>
     public const int OptionalBytesWrapperFieldNumber = 209;
     private static readonly pb::FieldCodec<pb::ByteString> _single_optionalBytesWrapper_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(1674);
@@ -1267,6 +1275,7 @@
       }
     }
 
+
     /// <summary>Field number for the "repeated_bool_wrapper" field.</summary>
     public const int RepeatedBoolWrapperFieldNumber = 211;
     private static readonly pb::FieldCodec<bool?> _repeated_repeatedBoolWrapper_codec
@@ -2598,13 +2607,13 @@
       }
       if (other.optionalNestedMessage_ != null) {
         if (optionalNestedMessage_ == null) {
-          optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
+          OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
         }
         OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
       }
       if (other.optionalForeignMessage_ != null) {
         if (optionalForeignMessage_ == null) {
-          optionalForeignMessage_ = new global::ProtobufTestMessages.Proto3.ForeignMessage();
+          OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage();
         }
         OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage);
       }
@@ -2622,7 +2631,7 @@
       }
       if (other.recursiveMessage_ != null) {
         if (recursiveMessage_ == null) {
-          recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
+          RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
         }
         RecursiveMessage.MergeFrom(other.RecursiveMessage);
       }
@@ -2722,37 +2731,37 @@
       repeatedBytesWrapper_.Add(other.repeatedBytesWrapper_);
       if (other.optionalDuration_ != null) {
         if (optionalDuration_ == null) {
-          optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+          OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration();
         }
         OptionalDuration.MergeFrom(other.OptionalDuration);
       }
       if (other.optionalTimestamp_ != null) {
         if (optionalTimestamp_ == null) {
-          optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+          OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp();
         }
         OptionalTimestamp.MergeFrom(other.OptionalTimestamp);
       }
       if (other.optionalFieldMask_ != null) {
         if (optionalFieldMask_ == null) {
-          optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+          OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask();
         }
         OptionalFieldMask.MergeFrom(other.OptionalFieldMask);
       }
       if (other.optionalStruct_ != null) {
         if (optionalStruct_ == null) {
-          optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+          OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct();
         }
         OptionalStruct.MergeFrom(other.OptionalStruct);
       }
       if (other.optionalAny_ != null) {
         if (optionalAny_ == null) {
-          optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any();
+          OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any();
         }
         OptionalAny.MergeFrom(other.OptionalAny);
       }
       if (other.optionalValue_ != null) {
         if (optionalValue_ == null) {
-          optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value();
+          OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value();
         }
         OptionalValue.MergeFrom(other.OptionalValue);
       }
@@ -2922,24 +2931,24 @@
           }
           case 146: {
             if (optionalNestedMessage_ == null) {
-              optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
+              OptionalNestedMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
             }
-            input.ReadMessage(optionalNestedMessage_);
+            input.ReadMessage(OptionalNestedMessage);
             break;
           }
           case 154: {
             if (optionalForeignMessage_ == null) {
-              optionalForeignMessage_ = new global::ProtobufTestMessages.Proto3.ForeignMessage();
+              OptionalForeignMessage = new global::ProtobufTestMessages.Proto3.ForeignMessage();
             }
-            input.ReadMessage(optionalForeignMessage_);
+            input.ReadMessage(OptionalForeignMessage);
             break;
           }
           case 168: {
-            optionalNestedEnum_ = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum();
+            OptionalNestedEnum = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum();
             break;
           }
           case 176: {
-            optionalForeignEnum_ = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum();
+            OptionalForeignEnum = (global::ProtobufTestMessages.Proto3.ForeignEnum) input.ReadEnum();
             break;
           }
           case 194: {
@@ -2952,9 +2961,9 @@
           }
           case 218: {
             if (recursiveMessage_ == null) {
-              recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
+              RecursiveMessage = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
             }
-            input.ReadMessage(recursiveMessage_);
+            input.ReadMessage(RecursiveMessage);
             break;
           }
           case 250:
@@ -3275,44 +3284,44 @@
           }
           case 2410: {
             if (optionalDuration_ == null) {
-              optionalDuration_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+              OptionalDuration = new global::Google.Protobuf.WellKnownTypes.Duration();
             }
-            input.ReadMessage(optionalDuration_);
+            input.ReadMessage(OptionalDuration);
             break;
           }
           case 2418: {
             if (optionalTimestamp_ == null) {
-              optionalTimestamp_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+              OptionalTimestamp = new global::Google.Protobuf.WellKnownTypes.Timestamp();
             }
-            input.ReadMessage(optionalTimestamp_);
+            input.ReadMessage(OptionalTimestamp);
             break;
           }
           case 2426: {
             if (optionalFieldMask_ == null) {
-              optionalFieldMask_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+              OptionalFieldMask = new global::Google.Protobuf.WellKnownTypes.FieldMask();
             }
-            input.ReadMessage(optionalFieldMask_);
+            input.ReadMessage(OptionalFieldMask);
             break;
           }
           case 2434: {
             if (optionalStruct_ == null) {
-              optionalStruct_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+              OptionalStruct = new global::Google.Protobuf.WellKnownTypes.Struct();
             }
-            input.ReadMessage(optionalStruct_);
+            input.ReadMessage(OptionalStruct);
             break;
           }
           case 2442: {
             if (optionalAny_ == null) {
-              optionalAny_ = new global::Google.Protobuf.WellKnownTypes.Any();
+              OptionalAny = new global::Google.Protobuf.WellKnownTypes.Any();
             }
-            input.ReadMessage(optionalAny_);
+            input.ReadMessage(OptionalAny);
             break;
           }
           case 2450: {
             if (optionalValue_ == null) {
-              optionalValue_ = new global::Google.Protobuf.WellKnownTypes.Value();
+              OptionalValue = new global::Google.Protobuf.WellKnownTypes.Value();
             }
-            input.ReadMessage(optionalValue_);
+            input.ReadMessage(OptionalValue);
             break;
           }
           case 2490: {
@@ -3560,7 +3569,7 @@
           }
           if (other.corecursive_ != null) {
             if (corecursive_ == null) {
-              corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
+              Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
             }
             Corecursive.MergeFrom(other.Corecursive);
           }
@@ -3581,9 +3590,9 @@
               }
               case 18: {
                 if (corecursive_ == null) {
-                  corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
+                  Corecursive = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
                 }
-                input.ReadMessage(corecursive_);
+                input.ReadMessage(Corecursive);
                 break;
               }
             }
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs
index 3ab5a48..2a9efe5 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs
@@ -1879,7 +1879,7 @@
       }
       if (other.bar_ != null) {
         if (bar_ == null) {
-          bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
+          Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
         }
         Bar.MergeFrom(other.Bar);
       }
@@ -1888,7 +1888,7 @@
       }
       if (other.fred_ != null) {
         if (fred_ == null) {
-          fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
+          Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
         }
         Fred.MergeFrom(other.Fred);
       }
@@ -1906,9 +1906,9 @@
             break;
           case 10: {
             if (bar_ == null) {
-              bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
+              Bar = new global::UnitTest.Issues.TestProtos.ComplexOptionType1();
             }
-            input.ReadMessage(bar_);
+            input.ReadMessage(Bar);
             break;
           }
           case 16: {
@@ -1917,9 +1917,9 @@
           }
           case 26: {
             if (fred_ == null) {
-              fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
+              Fred = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4();
             }
-            input.ReadMessage(fred_);
+            input.ReadMessage(Fred);
             break;
           }
           case 34: {
@@ -2462,7 +2462,7 @@
       }
       if (other.sub_ != null) {
         if (sub_ == null) {
-          sub_ = new global::UnitTest.Issues.TestProtos.Aggregate();
+          Sub = new global::UnitTest.Issues.TestProtos.Aggregate();
         }
         Sub.MergeFrom(other.Sub);
       }
@@ -2487,9 +2487,9 @@
           }
           case 26: {
             if (sub_ == null) {
-              sub_ = new global::UnitTest.Issues.TestProtos.Aggregate();
+              Sub = new global::UnitTest.Issues.TestProtos.Aggregate();
             }
-            input.ReadMessage(sub_);
+            input.ReadMessage(Sub);
             break;
           }
         }
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
index 819fc20..f27ab64 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
@@ -557,7 +557,7 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
-            value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
+            Value = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
             break;
           }
           case 18:
@@ -881,7 +881,7 @@
       primitiveArray_.Add(other.primitiveArray_);
       if (other.messageValue_ != null) {
         if (messageValue_ == null) {
-          messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
+          MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
         }
         MessageValue.MergeFrom(other.MessageValue);
       }
@@ -912,9 +912,9 @@
           }
           case 26: {
             if (messageValue_ == null) {
-              messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
+              MessageValue = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
             }
-            input.ReadMessage(messageValue_);
+            input.ReadMessage(MessageValue);
             break;
           }
           case 34: {
@@ -922,7 +922,7 @@
             break;
           }
           case 40: {
-            enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
+            EnumValue = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
             break;
           }
           case 50:
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
index 0422153..bbbee22 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
@@ -1307,19 +1307,19 @@
       }
       if (other.singleNestedMessage_ != null) {
         if (singleNestedMessage_ == null) {
-          singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+          SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
         }
         SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
       }
       if (other.singleForeignMessage_ != null) {
         if (singleForeignMessage_ == null) {
-          singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+          SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage();
         }
         SingleForeignMessage.MergeFrom(other.SingleForeignMessage);
       }
       if (other.singleImportMessage_ != null) {
         if (singleImportMessage_ == null) {
-          singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
+          SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage();
         }
         SingleImportMessage.MergeFrom(other.SingleImportMessage);
       }
@@ -1334,7 +1334,7 @@
       }
       if (other.singlePublicImportMessage_ != null) {
         if (singlePublicImportMessage_ == null) {
-          singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
+          SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage();
         }
         SinglePublicImportMessage.MergeFrom(other.SinglePublicImportMessage);
       }
@@ -1451,42 +1451,42 @@
           }
           case 146: {
             if (singleNestedMessage_ == null) {
-              singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+              SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
             }
-            input.ReadMessage(singleNestedMessage_);
+            input.ReadMessage(SingleNestedMessage);
             break;
           }
           case 154: {
             if (singleForeignMessage_ == null) {
-              singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+              SingleForeignMessage = new global::Google.Protobuf.TestProtos.ForeignMessage();
             }
-            input.ReadMessage(singleForeignMessage_);
+            input.ReadMessage(SingleForeignMessage);
             break;
           }
           case 162: {
             if (singleImportMessage_ == null) {
-              singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
+              SingleImportMessage = new global::Google.Protobuf.TestProtos.ImportMessage();
             }
-            input.ReadMessage(singleImportMessage_);
+            input.ReadMessage(SingleImportMessage);
             break;
           }
           case 168: {
-            singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            SingleNestedEnum = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum();
             break;
           }
           case 176: {
-            singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            SingleForeignEnum = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
             break;
           }
           case 184: {
-            singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum();
+            SingleImportEnum = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum();
             break;
           }
           case 210: {
             if (singlePublicImportMessage_ == null) {
-              singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
+              SinglePublicImportMessage = new global::Google.Protobuf.TestProtos.PublicImportMessage();
             }
-            input.ReadMessage(singlePublicImportMessage_);
+            input.ReadMessage(SinglePublicImportMessage);
             break;
           }
           case 250:
@@ -1918,13 +1918,13 @@
       }
       if (other.child_ != null) {
         if (child_ == null) {
-          child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
+          Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
         }
         Child.MergeFrom(other.Child);
       }
       if (other.payload_ != null) {
         if (payload_ == null) {
-          payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+          Payload = new global::Google.Protobuf.TestProtos.TestAllTypes();
         }
         Payload.MergeFrom(other.Payload);
       }
@@ -1942,16 +1942,16 @@
             break;
           case 10: {
             if (child_ == null) {
-              child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
+              Child = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
             }
-            input.ReadMessage(child_);
+            input.ReadMessage(Child);
             break;
           }
           case 18: {
             if (payload_ == null) {
-              payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+              Payload = new global::Google.Protobuf.TestProtos.TestAllTypes();
             }
-            input.ReadMessage(payload_);
+            input.ReadMessage(Payload);
             break;
           }
           case 26: {
@@ -2438,7 +2438,7 @@
       }
       if (other.foreignNested_ != null) {
         if (foreignNested_ == null) {
-          foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+          ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
         }
         ForeignNested.MergeFrom(other.ForeignNested);
       }
@@ -2455,9 +2455,9 @@
             break;
           case 10: {
             if (foreignNested_ == null) {
-              foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+              ForeignNested = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
             }
-            input.ReadMessage(foreignNested_);
+            input.ReadMessage(ForeignNested);
             break;
           }
         }
@@ -2758,7 +2758,7 @@
       }
       if (other.a_ != null) {
         if (a_ == null) {
-          a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
+          A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
         }
         A.MergeFrom(other.A);
       }
@@ -2778,9 +2778,9 @@
             break;
           case 10: {
             if (a_ == null) {
-              a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
+              A = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
             }
-            input.ReadMessage(a_);
+            input.ReadMessage(A);
             break;
           }
           case 16: {
@@ -2903,7 +2903,7 @@
       }
       if (other.bb_ != null) {
         if (bb_ == null) {
-          bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
+          Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
         }
         Bb.MergeFrom(other.Bb);
       }
@@ -2920,9 +2920,9 @@
             break;
           case 10: {
             if (bb_ == null) {
-              bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
+              Bb = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
             }
-            input.ReadMessage(bb_);
+            input.ReadMessage(Bb);
             break;
           }
         }
@@ -3059,7 +3059,7 @@
       }
       if (other.a_ != null) {
         if (a_ == null) {
-          a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
+          A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
         }
         A.MergeFrom(other.A);
       }
@@ -3079,9 +3079,9 @@
             break;
           case 10: {
             if (a_ == null) {
-              a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
+              A = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
             }
-            input.ReadMessage(a_);
+            input.ReadMessage(A);
             break;
           }
           case 16: {
@@ -3214,7 +3214,7 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
-            value_ = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum();
+            Value = (global::Google.Protobuf.TestProtos.TestEnumWithDupValue) input.ReadEnum();
             break;
           }
         }
@@ -3466,7 +3466,7 @@
       }
       if (other.messageField_ != null) {
         if (messageField_ == null) {
-          messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+          MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage();
         }
         MessageField.MergeFrom(other.MessageField);
       }
@@ -3494,14 +3494,14 @@
             break;
           }
           case 24: {
-            enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            EnumField = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
             break;
           }
           case 34: {
             if (messageField_ == null) {
-              messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+              MessageField = new global::Google.Protobuf.TestProtos.ForeignMessage();
             }
-            input.ReadMessage(messageField_);
+            input.ReadMessage(MessageField);
             break;
           }
           case 58:
@@ -3711,7 +3711,7 @@
       }
       if (other.singleNestedMessage_ != null) {
         if (singleNestedMessage_ == null) {
-          singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
+          SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
         }
         SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
       }
@@ -3740,9 +3740,9 @@
           }
           case 1602: {
             if (singleNestedMessage_ == null) {
-              singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
+              SingleNestedMessage = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
             }
-            input.ReadMessage(singleNestedMessage_);
+            input.ReadMessage(SingleNestedMessage);
             break;
           }
         }
@@ -4040,7 +4040,7 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
-            sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
+            SparseEnum = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
             break;
           }
         }
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
index fe91380..45f8ece 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
@@ -342,6 +342,7 @@
       }
     }
 
+
     /// <summary>Field number for the "float_field" field.</summary>
     public const int FloatFieldFieldNumber = 11;
     private static readonly pb::FieldCodec<float?> _single_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
@@ -354,6 +355,7 @@
       }
     }
 
+
     /// <summary>Field number for the "int64_field" field.</summary>
     public const int Int64FieldFieldNumber = 12;
     private static readonly pb::FieldCodec<long?> _single_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
@@ -366,6 +368,7 @@
       }
     }
 
+
     /// <summary>Field number for the "uint64_field" field.</summary>
     public const int Uint64FieldFieldNumber = 13;
     private static readonly pb::FieldCodec<ulong?> _single_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
@@ -378,6 +381,7 @@
       }
     }
 
+
     /// <summary>Field number for the "int32_field" field.</summary>
     public const int Int32FieldFieldNumber = 14;
     private static readonly pb::FieldCodec<int?> _single_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
@@ -390,6 +394,7 @@
       }
     }
 
+
     /// <summary>Field number for the "uint32_field" field.</summary>
     public const int Uint32FieldFieldNumber = 15;
     private static readonly pb::FieldCodec<uint?> _single_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
@@ -402,6 +407,7 @@
       }
     }
 
+
     /// <summary>Field number for the "bool_field" field.</summary>
     public const int BoolFieldFieldNumber = 16;
     private static readonly pb::FieldCodec<bool?> _single_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
@@ -414,6 +420,7 @@
       }
     }
 
+
     /// <summary>Field number for the "string_field" field.</summary>
     public const int StringFieldFieldNumber = 17;
     private static readonly pb::FieldCodec<string> _single_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
@@ -426,6 +433,7 @@
       }
     }
 
+
     /// <summary>Field number for the "bytes_field" field.</summary>
     public const int BytesFieldFieldNumber = 18;
     private static readonly pb::FieldCodec<pb::ByteString> _single_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
@@ -438,6 +446,7 @@
       }
     }
 
+
     /// <summary>Field number for the "value_field" field.</summary>
     public const int ValueFieldFieldNumber = 19;
     private global::Google.Protobuf.WellKnownTypes.Value valueField_;
@@ -667,55 +676,55 @@
       }
       if (other.anyField_ != null) {
         if (anyField_ == null) {
-          anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
+          AnyField = new global::Google.Protobuf.WellKnownTypes.Any();
         }
         AnyField.MergeFrom(other.AnyField);
       }
       if (other.apiField_ != null) {
         if (apiField_ == null) {
-          apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
+          ApiField = new global::Google.Protobuf.WellKnownTypes.Api();
         }
         ApiField.MergeFrom(other.ApiField);
       }
       if (other.durationField_ != null) {
         if (durationField_ == null) {
-          durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+          DurationField = new global::Google.Protobuf.WellKnownTypes.Duration();
         }
         DurationField.MergeFrom(other.DurationField);
       }
       if (other.emptyField_ != null) {
         if (emptyField_ == null) {
-          emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
+          EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty();
         }
         EmptyField.MergeFrom(other.EmptyField);
       }
       if (other.fieldMaskField_ != null) {
         if (fieldMaskField_ == null) {
-          fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+          FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask();
         }
         FieldMaskField.MergeFrom(other.FieldMaskField);
       }
       if (other.sourceContextField_ != null) {
         if (sourceContextField_ == null) {
-          sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+          SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext();
         }
         SourceContextField.MergeFrom(other.SourceContextField);
       }
       if (other.structField_ != null) {
         if (structField_ == null) {
-          structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+          StructField = new global::Google.Protobuf.WellKnownTypes.Struct();
         }
         StructField.MergeFrom(other.StructField);
       }
       if (other.timestampField_ != null) {
         if (timestampField_ == null) {
-          timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+          TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp();
         }
         TimestampField.MergeFrom(other.TimestampField);
       }
       if (other.typeField_ != null) {
         if (typeField_ == null) {
-          typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
+          TypeField = new global::Google.Protobuf.WellKnownTypes.Type();
         }
         TypeField.MergeFrom(other.TypeField);
       }
@@ -766,7 +775,7 @@
       }
       if (other.valueField_ != null) {
         if (valueField_ == null) {
-          valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
+          ValueField = new global::Google.Protobuf.WellKnownTypes.Value();
         }
         ValueField.MergeFrom(other.ValueField);
       }
@@ -783,65 +792,65 @@
             break;
           case 10: {
             if (anyField_ == null) {
-              anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
+              AnyField = new global::Google.Protobuf.WellKnownTypes.Any();
             }
-            input.ReadMessage(anyField_);
+            input.ReadMessage(AnyField);
             break;
           }
           case 18: {
             if (apiField_ == null) {
-              apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
+              ApiField = new global::Google.Protobuf.WellKnownTypes.Api();
             }
-            input.ReadMessage(apiField_);
+            input.ReadMessage(ApiField);
             break;
           }
           case 26: {
             if (durationField_ == null) {
-              durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+              DurationField = new global::Google.Protobuf.WellKnownTypes.Duration();
             }
-            input.ReadMessage(durationField_);
+            input.ReadMessage(DurationField);
             break;
           }
           case 34: {
             if (emptyField_ == null) {
-              emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
+              EmptyField = new global::Google.Protobuf.WellKnownTypes.Empty();
             }
-            input.ReadMessage(emptyField_);
+            input.ReadMessage(EmptyField);
             break;
           }
           case 42: {
             if (fieldMaskField_ == null) {
-              fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+              FieldMaskField = new global::Google.Protobuf.WellKnownTypes.FieldMask();
             }
-            input.ReadMessage(fieldMaskField_);
+            input.ReadMessage(FieldMaskField);
             break;
           }
           case 50: {
             if (sourceContextField_ == null) {
-              sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+              SourceContextField = new global::Google.Protobuf.WellKnownTypes.SourceContext();
             }
-            input.ReadMessage(sourceContextField_);
+            input.ReadMessage(SourceContextField);
             break;
           }
           case 58: {
             if (structField_ == null) {
-              structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+              StructField = new global::Google.Protobuf.WellKnownTypes.Struct();
             }
-            input.ReadMessage(structField_);
+            input.ReadMessage(StructField);
             break;
           }
           case 66: {
             if (timestampField_ == null) {
-              timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+              TimestampField = new global::Google.Protobuf.WellKnownTypes.Timestamp();
             }
-            input.ReadMessage(timestampField_);
+            input.ReadMessage(TimestampField);
             break;
           }
           case 74: {
             if (typeField_ == null) {
-              typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
+              TypeField = new global::Google.Protobuf.WellKnownTypes.Type();
             }
-            input.ReadMessage(typeField_);
+            input.ReadMessage(TypeField);
             break;
           }
           case 82: {
@@ -909,9 +918,9 @@
           }
           case 154: {
             if (valueField_ == null) {
-              valueField_ = new global::Google.Protobuf.WellKnownTypes.Value();
+              ValueField = new global::Google.Protobuf.WellKnownTypes.Value();
             }
-            input.ReadMessage(valueField_);
+            input.ReadMessage(ValueField);
             break;
           }
         }
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs
index dbbcc14..1924439 100644
--- a/csharp/src/Google.Protobuf/Collections/MapField.cs
+++ b/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -1,771 +1,771 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2015 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using Google.Protobuf.Compatibility;
-using Google.Protobuf.Reflection;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace Google.Protobuf.Collections
-{
-    /// <summary>
-    /// Representation of a map field in a Protocol Buffer message.
-    /// </summary>
-    /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
-    /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
-    /// <remarks>
-    /// <para>
-    /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />.
-    /// </para>
-    /// <para>
-    /// Null values are not permitted in the map, either for wrapper types or regular messages.
-    /// If a map is deserialized from a data stream and the value is missing from an entry, a default value
-    /// is created instead. For primitive types, that is the regular default value (0, the empty string and so
-    /// on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length
-    /// encoded value for the field.
-    /// </para>
-    /// <para>
-    /// This implementation does not generally prohibit the use of key/value types which are not
-    /// supported by Protocol Buffers (e.g. using a key type of <code>byte</code>) but nor does it guarantee
-    /// that all operations will work in such cases.
-    /// </para>
-    /// <para>
-    /// The order in which entries are returned when iterating over this object is undefined, and may change
-    /// in future versions.
-    /// </para>
-    /// </remarks>
-    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
-#if !NET35
-        , IReadOnlyDictionary<TKey, TValue>
-#endif
-    {
-        private static readonly EqualityComparer<TValue> ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TValue>();
-        private static readonly EqualityComparer<TKey> KeyEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TKey>();
-
-        // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
-        private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
-            new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(KeyEqualityComparer);
-        private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
-
-        /// <summary>
-        /// Creates a deep clone of this object.
-        /// </summary>
-        /// <returns>
-        /// A deep clone of this object.
-        /// </returns>
-        public MapField<TKey, TValue> Clone()
-        {
-            var clone = new MapField<TKey, TValue>();
-            // Keys are never cloneable. Values might be.
-            if (typeof(IDeepCloneable<TValue>).IsAssignableFrom(typeof(TValue)))
-            {
-                foreach (var pair in list)
-                {
-                    clone.Add(pair.Key, ((IDeepCloneable<TValue>)pair.Value).Clone());
-                }
-            }
-            else
-            {
-                // Nothing is cloneable, so we don't need to worry.
-                clone.Add(this);
-            }
-            return clone;
-        }
-
-        /// <summary>
-        /// Adds the specified key/value pair to the map.
-        /// </summary>
-        /// <remarks>
-        /// This operation fails if the key already exists in the map. To replace an existing entry, use the indexer.
-        /// </remarks>
-        /// <param name="key">The key to add</param>
-        /// <param name="value">The value to add.</param>
-        /// <exception cref="System.ArgumentException">The given key already exists in map.</exception>
-        public void Add(TKey key, TValue value)
-        {
-            // Validation of arguments happens in ContainsKey and the indexer
-            if (ContainsKey(key))
-            {
-                throw new ArgumentException("Key already exists in map", nameof(key));
-            }
-            this[key] = value;
-        }
-
-        /// <summary>
-        /// Determines whether the specified key is present in the map.
-        /// </summary>
-        /// <param name="key">The key to check.</param>
-        /// <returns><c>true</c> if the map contains the given key; <c>false</c> otherwise.</returns>
-        public bool ContainsKey(TKey key)
-        {
-            ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
-            return map.ContainsKey(key);
-        }
-
-        private bool ContainsValue(TValue value) =>
-            list.Any(pair => ValueEqualityComparer.Equals(pair.Value, value));
-
-        /// <summary>
-        /// Removes the entry identified by the given key from the map.
-        /// </summary>
-        /// <param name="key">The key indicating the entry to remove from the map.</param>
-        /// <returns><c>true</c> if the map contained the given key before the entry was removed; <c>false</c> otherwise.</returns>
-        public bool Remove(TKey key)
-        {
-            ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
-            LinkedListNode<KeyValuePair<TKey, TValue>> node;
-            if (map.TryGetValue(key, out node))
-            {
-                map.Remove(key);
-                node.List.Remove(node);
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        /// <summary>
-        /// Gets the value associated with the specified key.
-        /// </summary>
-        /// <param name="key">The key whose value to get.</param>
-        /// <param name="value">When this method returns, the value associated with the specified key, if the key is found;
-        /// otherwise, the default value for the type of the <paramref name="value"/> parameter.
-        /// This parameter is passed uninitialized.</param>
-        /// <returns><c>true</c> if the map contains an element with the specified key; otherwise, <c>false</c>.</returns>
-        public bool TryGetValue(TKey key, out TValue value)
-        {
-            LinkedListNode<KeyValuePair<TKey, TValue>> node;
-            if (map.TryGetValue(key, out node))
-            {
-                value = node.Value.Value;
-                return true;
-            }
-            else
-            {
-                value = default(TValue);
-                return false;
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets the value associated with the specified key.
-        /// </summary>
-        /// <param name="key">The key of the value to get or set.</param>
-        /// <exception cref="KeyNotFoundException">The property is retrieved and key does not exist in the collection.</exception>
-        /// <returns>The value associated with the specified key. If the specified key is not found,
-        /// a get operation throws a <see cref="KeyNotFoundException"/>, and a set operation creates a new element with the specified key.</returns>
-        public TValue this[TKey key]
-        {
-            get
-            {
-                ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
-                TValue value;
-                if (TryGetValue(key, out value))
-                {
-                    return value;
-                }
-                throw new KeyNotFoundException();
-            }
-            set
-            {
-                ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
-                // value == null check here is redundant, but avoids boxing.
-                if (value == null)
-                {
-                    ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
-                }
-                LinkedListNode<KeyValuePair<TKey, TValue>> node;
-                var pair = new KeyValuePair<TKey, TValue>(key, value);
-                if (map.TryGetValue(key, out node))
-                {
-                    node.Value = pair;
-                }
-                else
-                {
-                    node = list.AddLast(pair);
-                    map[key] = node;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets a collection containing the keys in the map.
-        /// </summary>
-        public ICollection<TKey> Keys { get { return new MapView<TKey>(this, pair => pair.Key, ContainsKey); } }
-
-        /// <summary>
-        /// Gets a collection containing the values in the map.
-        /// </summary>
-        public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } }
-
-        /// <summary>
-        /// Adds the specified entries to the map. The keys and values are not automatically cloned.
-        /// </summary>
-        /// <param name="entries">The entries to add to the map.</param>
-        public void Add(IDictionary<TKey, TValue> entries)
-        {
-            ProtoPreconditions.CheckNotNull(entries, nameof(entries));
-            foreach (var pair in entries)
-            {
-                Add(pair.Key, pair.Value);
-            }
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through the collection.
-        /// </summary>
-        /// <returns>
-        /// An enumerator that can be used to iterate through the collection.
-        /// </returns>
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-        {
-            return list.GetEnumerator();
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through a collection.
-        /// </summary>
-        /// <returns>
-        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
-        /// </returns>
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
-
-        /// <summary>
-        /// Adds the specified item to the map.
-        /// </summary>
-        /// <param name="item">The item to add to the map.</param>
-        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
-        {
-            Add(item.Key, item.Value);
-        }
-
-        /// <summary>
-        /// Removes all items from the map.
-        /// </summary>
-        public void Clear()
-        {
-            list.Clear();
-            map.Clear();
-        }
-
-        /// <summary>
-        /// Determines whether map contains an entry equivalent to the given key/value pair.
-        /// </summary>
-        /// <param name="item">The key/value pair to find.</param>
-        /// <returns></returns>
-        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
-        {
-            TValue value;
-            return TryGetValue(item.Key, out value) && ValueEqualityComparer.Equals(item.Value, value);
-        }
-
-        /// <summary>
-        /// Copies the key/value pairs in this map to an array.
-        /// </summary>
-        /// <param name="array">The array to copy the entries into.</param>
-        /// <param name="arrayIndex">The index of the array at which to start copying values.</param>
-        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
-        {
-            list.CopyTo(array, arrayIndex);
-        }
-
-        /// <summary>
-        /// Removes the specified key/value pair from the map.
-        /// </summary>
-        /// <remarks>Both the key and the value must be found for the entry to be removed.</remarks>
-        /// <param name="item">The key/value pair to remove.</param>
-        /// <returns><c>true</c> if the key/value pair was found and removed; <c>false</c> otherwise.</returns>
-        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
-        {
-            if (item.Key == null)
-            {
-                throw new ArgumentException("Key is null", nameof(item));
-            }
-            LinkedListNode<KeyValuePair<TKey, TValue>> node;
-            if (map.TryGetValue(item.Key, out node) &&
-                EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.Value))
-            {
-                map.Remove(item.Key);
-                node.List.Remove(node);
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        /// <summary>
-        /// Gets the number of elements contained in the map.
-        /// </summary>
-        public int Count { get { return list.Count; } }
-
-        /// <summary>
-        /// Gets a value indicating whether the map is read-only.
-        /// </summary>
-        public bool IsReadOnly { get { return false; } }
-
-        /// <summary>
-        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
-        /// </summary>
-        /// <param name="other">The <see cref="System.Object" /> to compare with this instance.</param>
-        /// <returns>
-        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
-        /// </returns>
-        public override bool Equals(object other)
-        {
-            return Equals(other as MapField<TKey, TValue>);
-        }
-
-        /// <summary>
-        /// Returns a hash code for this instance.
-        /// </summary>
-        /// <returns>
-        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
-        /// </returns>
-        public override int GetHashCode()
-        {
-            var keyComparer = KeyEqualityComparer;
-            var valueComparer = ValueEqualityComparer;
-            int hash = 0;
-            foreach (var pair in list)
-            {
-                hash ^= keyComparer.GetHashCode(pair.Key) * 31 + valueComparer.GetHashCode(pair.Value);
-            }
-            return hash;
-        }
-
-        /// <summary>
-        /// Compares this map with another for equality.
-        /// </summary>
-        /// <remarks>
-        /// The order of the key/value pairs in the maps is not deemed significant in this comparison.
-        /// </remarks>
-        /// <param name="other">The map to compare this with.</param>
-        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal map; <c>false</c> otherwise.</returns>
-        public bool Equals(MapField<TKey, TValue> other)
-        {
-            if (other == null)
-            {
-                return false;
-            }
-            if (other == this)
-            {
-                return true;
-            }
-            if (other.Count != this.Count)
-            {
-                return false;
-            }
-            var valueComparer = ValueEqualityComparer;
-            foreach (var pair in this)
-            {
-                TValue value;
-                if (!other.TryGetValue(pair.Key, out value))
-                {
-                    return false;
-                }
-                if (!valueComparer.Equals(value, pair.Value))
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        /// <summary>
-        /// Adds entries to the map from the given stream.
-        /// </summary>
-        /// <remarks>
-        /// It is assumed that the stream is initially positioned after the tag specified by the codec.
-        /// This method will continue reading entries from the stream until the end is reached, or
-        /// a different tag is encountered.
-        /// </remarks>
-        /// <param name="input">Stream to read from</param>
-        /// <param name="codec">Codec describing how the key/value pairs are encoded</param>
-        public void AddEntriesFrom(CodedInputStream input, Codec codec)
-        {
-            var adapter = new Codec.MessageAdapter(codec);
-            do
-            {
-                adapter.Reset();
-                input.ReadMessage(adapter);
-                this[adapter.Key] = adapter.Value;
-            } while (input.MaybeConsumeTag(codec.MapTag));
-        }
-
-        /// <summary>
-        /// Writes the contents of this map to the given coded output stream, using the specified codec
-        /// to encode each entry.
-        /// </summary>
-        /// <param name="output">The output stream to write to.</param>
-        /// <param name="codec">The codec to use for each entry.</param>
-        public void WriteTo(CodedOutputStream output, Codec codec)
-        {
-            var message = new Codec.MessageAdapter(codec);
-            foreach (var entry in list)
-            {
-                message.Key = entry.Key;
-                message.Value = entry.Value;
-                output.WriteTag(codec.MapTag);
-                output.WriteMessage(message);
-            }
-        }
-
-        /// <summary>
-        /// Calculates the size of this map based on the given entry codec.
-        /// </summary>
-        /// <param name="codec">The codec to use to encode each entry.</param>
-        /// <returns></returns>
-        public int CalculateSize(Codec codec)
-        {
-            if (Count == 0)
-            {
-                return 0;
-            }
-            var message = new Codec.MessageAdapter(codec);
-            int size = 0;
-            foreach (var entry in list)
-            {
-                message.Key = entry.Key;
-                message.Value = entry.Value;
-                size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);
-                size += CodedOutputStream.ComputeMessageSize(message);
-            }
-            return size;
-        }
-
-        /// <summary>
-        /// Returns a string representation of this repeated field, in the same
-        /// way as it would be represented by the default JSON formatter.
-        /// </summary>
-        public override string ToString()
-        {
-            var writer = new StringWriter();
-            JsonFormatter.Default.WriteDictionary(writer, this);
-            return writer.ToString();
-        }
-
-        #region IDictionary explicit interface implementation
-        void IDictionary.Add(object key, object value)
-        {
-            Add((TKey)key, (TValue)value);
-        }
-
-        bool IDictionary.Contains(object key)
-        {
-            if (!(key is TKey))
-            {
-                return false;
-            }
-            return ContainsKey((TKey)key);
-        }
-
-        IDictionaryEnumerator IDictionary.GetEnumerator()
-        {
-            return new DictionaryEnumerator(GetEnumerator());
-        }
-
-        void IDictionary.Remove(object key)
-        {
-            ProtoPreconditions.CheckNotNull(key, nameof(key));
-            if (!(key is TKey))
-            {
-                return;
-            }
-            Remove((TKey)key);
-        }
-
-        void ICollection.CopyTo(Array array, int index)
-        {
-            // This is ugly and slow as heck, but with any luck it will never be used anyway.
-            ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key, pair.Value)).ToList();
-            temp.CopyTo(array, index);
-        }
-
-        bool IDictionary.IsFixedSize { get { return false; } }
-
-        ICollection IDictionary.Keys { get { return (ICollection)Keys; } }
-
-        ICollection IDictionary.Values { get { return (ICollection)Values; } }
-
-        bool ICollection.IsSynchronized { get { return false; } }
-
-        object ICollection.SyncRoot { get { return this; } }
-
-        object IDictionary.this[object key]
-        {
-            get
-            {
-                ProtoPreconditions.CheckNotNull(key, nameof(key));
-                if (!(key is TKey))
-                {
-                    return null;
-                }
-                TValue value;
-                TryGetValue((TKey)key, out value);
-                return value;
-            }
-
-            set
-            {
-                this[(TKey)key] = (TValue)value;
-            }
-        }
-        #endregion
-
-        #region IReadOnlyDictionary explicit interface implementation
-#if !NET35
-        IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;
-
-        IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
-#endif
-        #endregion
-
-        private class DictionaryEnumerator : IDictionaryEnumerator
-        {
-            private readonly IEnumerator<KeyValuePair<TKey, TValue>> enumerator;
-
-            internal DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator)
-            {
-                this.enumerator = enumerator;
-            }
-
-            public bool MoveNext()
-            {
-                return enumerator.MoveNext();
-            }
-
-            public void Reset()
-            {
-                enumerator.Reset();
-            }
-
-            public object Current { get { return Entry; } }
-            public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
-            public object Key { get { return enumerator.Current.Key; } }
-            public object Value { get { return enumerator.Current.Value; } }
-        }
-
-        /// <summary>
-        /// A codec for a specific map field. This contains all the information required to encode and
-        /// decode the nested messages.
-        /// </summary>
-        public sealed class Codec
-        {
-            private readonly FieldCodec<TKey> keyCodec;
-            private readonly FieldCodec<TValue> valueCodec;
-            private readonly uint mapTag;
-
-            /// <summary>
-            /// Creates a new entry codec based on a separate key codec and value codec,
-            /// and the tag to use for each map entry.
-            /// </summary>
-            /// <param name="keyCodec">The key codec.</param>
-            /// <param name="valueCodec">The value codec.</param>
-            /// <param name="mapTag">The map tag to use to introduce each map entry.</param>
-            public Codec(FieldCodec<TKey> keyCodec, FieldCodec<TValue> valueCodec, uint mapTag)
-            {
-                this.keyCodec = keyCodec;
-                this.valueCodec = valueCodec;
-                this.mapTag = mapTag;
-            }
-
-            /// <summary>
-            /// The tag used in the enclosing message to indicate map entries.
-            /// </summary>
-            internal uint MapTag { get { return mapTag; } }
-
-            /// <summary>
-            /// A mutable message class, used for parsing and serializing. This
-            /// delegates the work to a codec, but implements the <see cref="IMessage"/> interface
-            /// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.
-            /// This is nested inside Codec as it's tightly coupled to the associated codec,
-            /// and it's simpler if it has direct access to all its fields.
-            /// </summary>
-            internal class MessageAdapter : IMessage
-            {
-                private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };
-
-                private readonly Codec codec;
-                internal TKey Key { get; set; }
-                internal TValue Value { get; set; }
-
-                internal MessageAdapter(Codec codec)
-                {
-                    this.codec = codec;
-                }
-
-                internal void Reset()
-                {
-                    Key = codec.keyCodec.DefaultValue;
-                    Value = codec.valueCodec.DefaultValue;
-                }
-
-                public void MergeFrom(CodedInputStream input)
-                {
-                    uint tag;
-                    while ((tag = input.ReadTag()) != 0)
-                    {
-                        if (tag == codec.keyCodec.Tag)
-                        {
-                            Key = codec.keyCodec.Read(input);
-                        }
-                        else if (tag == codec.valueCodec.Tag)
-                        {
-                            Value = codec.valueCodec.Read(input);
-                        }
-                        else 
-                        {
-                            input.SkipLastField();
-                        }
-                    }
-
-                    // Corner case: a map entry with a key but no value, where the value type is a message.
-                    // Read it as if we'd seen an input stream with no data (i.e. create a "default" message).
-                    if (Value == null)
-                    {
-                        Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
-                    }
-                }
-
-                public void WriteTo(CodedOutputStream output)
-                {
-                    codec.keyCodec.WriteTagAndValue(output, Key);
-                    codec.valueCodec.WriteTagAndValue(output, Value);
-                }
-
-                public int CalculateSize()
-                {
-                    return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);
-                }
-
-                MessageDescriptor IMessage.Descriptor { get { return null; } }
-            }
-        }
-
-        private class MapView<T> : ICollection<T>, ICollection
-        {
-            private readonly MapField<TKey, TValue> parent;
-            private readonly Func<KeyValuePair<TKey, TValue>, T> projection;
-            private readonly Func<T, bool> containsCheck;
-
-            internal MapView(
-                MapField<TKey, TValue> parent,
-                Func<KeyValuePair<TKey, TValue>, T> projection,
-                Func<T, bool> containsCheck)
-            {
-                this.parent = parent;
-                this.projection = projection;
-                this.containsCheck = containsCheck;
-            }
-
-            public int Count { get { return parent.Count; } }
-
-            public bool IsReadOnly { get { return true; } }
-
-            public bool IsSynchronized { get { return false; } }
-
-            public object SyncRoot { get { return parent; } }
-
-            public void Add(T item)
-            {
-                throw new NotSupportedException();
-            }
-
-            public void Clear()
-            {
-                throw new NotSupportedException();
-            }
-
-            public bool Contains(T item)
-            {
-                return containsCheck(item);
-            }
-
-            public void CopyTo(T[] array, int arrayIndex)
-            {
-                if (arrayIndex < 0)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(arrayIndex));
-                }
-                if (arrayIndex + Count > array.Length)
-                {
-                    throw new ArgumentException("Not enough space in the array", nameof(array));
-                }
-                foreach (var item in this)
-                {
-                    array[arrayIndex++] = item;
-                }
-            }
-
-            public IEnumerator<T> GetEnumerator()
-            {
-                return parent.list.Select(projection).GetEnumerator();
-            }
-
-            public bool Remove(T item)
-            {
-                throw new NotSupportedException();
-            }
-
-            IEnumerator IEnumerable.GetEnumerator()
-            {
-                return GetEnumerator();
-            }
-
-            public void CopyTo(Array array, int index)
-            {
-                if (index < 0)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(index));
-                }
-                if (index + Count > array.Length)
-                {
-                    throw new ArgumentException("Not enough space in the array", nameof(array));
-                }
-                foreach (var item in this)
-                {
-                    array.SetValue(item, index++);
-                }
-            }
-        }
-    }
-}
+#region Copyright notice and license

+// Protocol Buffers - Google's data interchange format

+// Copyright 2015 Google Inc.  All rights reserved.

+// https://developers.google.com/protocol-buffers/

+//

+// Redistribution and use in source and binary forms, with or without

+// modification, are permitted provided that the following conditions are

+// met:

+//

+//     * Redistributions of source code must retain the above copyright

+// notice, this list of conditions and the following disclaimer.

+//     * Redistributions in binary form must reproduce the above

+// copyright notice, this list of conditions and the following disclaimer

+// in the documentation and/or other materials provided with the

+// distribution.

+//     * Neither the name of Google Inc. nor the names of its

+// contributors may be used to endorse or promote products derived from

+// this software without specific prior written permission.

+//

+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#endregion

+

+using Google.Protobuf.Compatibility;

+using Google.Protobuf.Reflection;

+using System;

+using System.Collections;

+using System.Collections.Generic;

+using System.IO;

+using System.Linq;

+

+namespace Google.Protobuf.Collections

+{

+    /// <summary>

+    /// Representation of a map field in a Protocol Buffer message.

+    /// </summary>

+    /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>

+    /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>

+    /// <remarks>

+    /// <para>

+    /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />.

+    /// </para>

+    /// <para>

+    /// Null values are not permitted in the map, either for wrapper types or regular messages.

+    /// If a map is deserialized from a data stream and the value is missing from an entry, a default value

+    /// is created instead. For primitive types, that is the regular default value (0, the empty string and so

+    /// on); for message types, an empty instance of the message is created, as if the map entry contained a 0-length

+    /// encoded value for the field.

+    /// </para>

+    /// <para>

+    /// This implementation does not generally prohibit the use of key/value types which are not

+    /// supported by Protocol Buffers (e.g. using a key type of <code>byte</code>) but nor does it guarantee

+    /// that all operations will work in such cases.

+    /// </para>

+    /// <para>

+    /// The order in which entries are returned when iterating over this object is undefined, and may change

+    /// in future versions.

+    /// </para>

+    /// </remarks>

+    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary

+#if !NET35

+        , IReadOnlyDictionary<TKey, TValue>

+#endif

+    {

+        private static readonly EqualityComparer<TValue> ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TValue>();

+        private static readonly EqualityComparer<TKey> KeyEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TKey>();

+

+        // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)

+        private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =

+            new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(KeyEqualityComparer);

+        private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();

+

+        /// <summary>

+        /// Creates a deep clone of this object.

+        /// </summary>

+        /// <returns>

+        /// A deep clone of this object.

+        /// </returns>

+        public MapField<TKey, TValue> Clone()

+        {

+            var clone = new MapField<TKey, TValue>();

+            // Keys are never cloneable. Values might be.

+            if (typeof(IDeepCloneable<TValue>).IsAssignableFrom(typeof(TValue)))

+            {

+                foreach (var pair in list)

+                {

+                    clone.Add(pair.Key, ((IDeepCloneable<TValue>)pair.Value).Clone());

+                }

+            }

+            else

+            {

+                // Nothing is cloneable, so we don't need to worry.

+                clone.Add(this);

+            }

+            return clone;

+        }

+

+        /// <summary>

+        /// Adds the specified key/value pair to the map.

+        /// </summary>

+        /// <remarks>

+        /// This operation fails if the key already exists in the map. To replace an existing entry, use the indexer.

+        /// </remarks>

+        /// <param name="key">The key to add</param>

+        /// <param name="value">The value to add.</param>

+        /// <exception cref="System.ArgumentException">The given key already exists in map.</exception>

+        public void Add(TKey key, TValue value)

+        {

+            // Validation of arguments happens in ContainsKey and the indexer

+            if (ContainsKey(key))

+            {

+                throw new ArgumentException("Key already exists in map", nameof(key));

+            }

+            this[key] = value;

+        }

+

+        /// <summary>

+        /// Determines whether the specified key is present in the map.

+        /// </summary>

+        /// <param name="key">The key to check.</param>

+        /// <returns><c>true</c> if the map contains the given key; <c>false</c> otherwise.</returns>

+        public bool ContainsKey(TKey key)

+        {

+            ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));

+            return map.ContainsKey(key);

+        }

+

+        private bool ContainsValue(TValue value) =>

+            list.Any(pair => ValueEqualityComparer.Equals(pair.Value, value));

+

+        /// <summary>

+        /// Removes the entry identified by the given key from the map.

+        /// </summary>

+        /// <param name="key">The key indicating the entry to remove from the map.</param>

+        /// <returns><c>true</c> if the map contained the given key before the entry was removed; <c>false</c> otherwise.</returns>

+        public bool Remove(TKey key)

+        {

+            ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));

+            LinkedListNode<KeyValuePair<TKey, TValue>> node;

+            if (map.TryGetValue(key, out node))

+            {

+                map.Remove(key);

+                node.List.Remove(node);

+                return true;

+            }

+            else

+            {

+                return false;

+            }

+        }

+

+        /// <summary>

+        /// Gets the value associated with the specified key.

+        /// </summary>

+        /// <param name="key">The key whose value to get.</param>

+        /// <param name="value">When this method returns, the value associated with the specified key, if the key is found;

+        /// otherwise, the default value for the type of the <paramref name="value"/> parameter.

+        /// This parameter is passed uninitialized.</param>

+        /// <returns><c>true</c> if the map contains an element with the specified key; otherwise, <c>false</c>.</returns>

+        public bool TryGetValue(TKey key, out TValue value)

+        {

+            LinkedListNode<KeyValuePair<TKey, TValue>> node;

+            if (map.TryGetValue(key, out node))

+            {

+                value = node.Value.Value;

+                return true;

+            }

+            else

+            {

+                value = default(TValue);

+                return false;

+            }

+        }

+

+        /// <summary>

+        /// Gets or sets the value associated with the specified key.

+        /// </summary>

+        /// <param name="key">The key of the value to get or set.</param>

+        /// <exception cref="KeyNotFoundException">The property is retrieved and key does not exist in the collection.</exception>

+        /// <returns>The value associated with the specified key. If the specified key is not found,

+        /// a get operation throws a <see cref="KeyNotFoundException"/>, and a set operation creates a new element with the specified key.</returns>

+        public TValue this[TKey key]

+        {

+            get

+            {

+                ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));

+                TValue value;

+                if (TryGetValue(key, out value))

+                {

+                    return value;

+                }

+                throw new KeyNotFoundException();

+            }

+            set

+            {

+                ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));

+                // value == null check here is redundant, but avoids boxing.

+                if (value == null)

+                {

+                    ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));

+                }

+                LinkedListNode<KeyValuePair<TKey, TValue>> node;

+                var pair = new KeyValuePair<TKey, TValue>(key, value);

+                if (map.TryGetValue(key, out node))

+                {

+                    node.Value = pair;

+                }

+                else

+                {

+                    node = list.AddLast(pair);

+                    map[key] = node;

+                }

+            }

+        }

+

+        /// <summary>

+        /// Gets a collection containing the keys in the map.

+        /// </summary>

+        public ICollection<TKey> Keys { get { return new MapView<TKey>(this, pair => pair.Key, ContainsKey); } }

+

+        /// <summary>

+        /// Gets a collection containing the values in the map.

+        /// </summary>

+        public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } }

+

+        /// <summary>

+        /// Adds the specified entries to the map. The keys and values are not automatically cloned.

+        /// </summary>

+        /// <param name="entries">The entries to add to the map.</param>

+        public void Add(IDictionary<TKey, TValue> entries)

+        {

+            ProtoPreconditions.CheckNotNull(entries, nameof(entries));

+            foreach (var pair in entries)

+            {

+                Add(pair.Key, pair.Value);

+            }

+        }

+

+        /// <summary>

+        /// Returns an enumerator that iterates through the collection.

+        /// </summary>

+        /// <returns>

+        /// An enumerator that can be used to iterate through the collection.

+        /// </returns>

+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()

+        {

+            return list.GetEnumerator();

+        }

+

+        /// <summary>

+        /// Returns an enumerator that iterates through a collection.

+        /// </summary>

+        /// <returns>

+        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.

+        /// </returns>

+        IEnumerator IEnumerable.GetEnumerator()

+        {

+            return GetEnumerator();

+        }

+

+        /// <summary>

+        /// Adds the specified item to the map.

+        /// </summary>

+        /// <param name="item">The item to add to the map.</param>

+        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)

+        {

+            Add(item.Key, item.Value);

+        }

+

+        /// <summary>

+        /// Removes all items from the map.

+        /// </summary>

+        public void Clear()

+        {

+            list.Clear();

+            map.Clear();

+        }

+

+        /// <summary>

+        /// Determines whether map contains an entry equivalent to the given key/value pair.

+        /// </summary>

+        /// <param name="item">The key/value pair to find.</param>

+        /// <returns></returns>

+        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)

+        {

+            TValue value;

+            return TryGetValue(item.Key, out value) && ValueEqualityComparer.Equals(item.Value, value);

+        }

+

+        /// <summary>

+        /// Copies the key/value pairs in this map to an array.

+        /// </summary>

+        /// <param name="array">The array to copy the entries into.</param>

+        /// <param name="arrayIndex">The index of the array at which to start copying values.</param>

+        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)

+        {

+            list.CopyTo(array, arrayIndex);

+        }

+

+        /// <summary>

+        /// Removes the specified key/value pair from the map.

+        /// </summary>

+        /// <remarks>Both the key and the value must be found for the entry to be removed.</remarks>

+        /// <param name="item">The key/value pair to remove.</param>

+        /// <returns><c>true</c> if the key/value pair was found and removed; <c>false</c> otherwise.</returns>

+        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)

+        {

+            if (item.Key == null)

+            {

+                throw new ArgumentException("Key is null", nameof(item));

+            }

+            LinkedListNode<KeyValuePair<TKey, TValue>> node;

+            if (map.TryGetValue(item.Key, out node) &&

+                EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.Value))

+            {

+                map.Remove(item.Key);

+                node.List.Remove(node);

+                return true;

+            }

+            else

+            {

+                return false;

+            }

+        }

+

+        /// <summary>

+        /// Gets the number of elements contained in the map.

+        /// </summary>

+        public int Count { get { return list.Count; } }

+

+        /// <summary>

+        /// Gets a value indicating whether the map is read-only.

+        /// </summary>

+        public bool IsReadOnly { get { return false; } }

+

+        /// <summary>

+        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.

+        /// </summary>

+        /// <param name="other">The <see cref="System.Object" /> to compare with this instance.</param>

+        /// <returns>

+        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.

+        /// </returns>

+        public override bool Equals(object other)

+        {

+            return Equals(other as MapField<TKey, TValue>);

+        }

+

+        /// <summary>

+        /// Returns a hash code for this instance.

+        /// </summary>

+        /// <returns>

+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 

+        /// </returns>

+        public override int GetHashCode()

+        {

+            var keyComparer = KeyEqualityComparer;

+            var valueComparer = ValueEqualityComparer;

+            int hash = 0;

+            foreach (var pair in list)

+            {

+                hash ^= keyComparer.GetHashCode(pair.Key) * 31 + valueComparer.GetHashCode(pair.Value);

+            }

+            return hash;

+        }

+

+        /// <summary>

+        /// Compares this map with another for equality.

+        /// </summary>

+        /// <remarks>

+        /// The order of the key/value pairs in the maps is not deemed significant in this comparison.

+        /// </remarks>

+        /// <param name="other">The map to compare this with.</param>

+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal map; <c>false</c> otherwise.</returns>

+        public bool Equals(MapField<TKey, TValue> other)

+        {

+            if (other == null)

+            {

+                return false;

+            }

+            if (other == this)

+            {

+                return true;

+            }

+            if (other.Count != this.Count)

+            {

+                return false;

+            }

+            var valueComparer = ValueEqualityComparer;

+            foreach (var pair in this)

+            {

+                TValue value;

+                if (!other.TryGetValue(pair.Key, out value))

+                {

+                    return false;

+                }

+                if (!valueComparer.Equals(value, pair.Value))

+                {

+                    return false;

+                }

+            }

+            return true;

+        }

+

+        /// <summary>

+        /// Adds entries to the map from the given stream.

+        /// </summary>

+        /// <remarks>

+        /// It is assumed that the stream is initially positioned after the tag specified by the codec.

+        /// This method will continue reading entries from the stream until the end is reached, or

+        /// a different tag is encountered.

+        /// </remarks>

+        /// <param name="input">Stream to read from</param>

+        /// <param name="codec">Codec describing how the key/value pairs are encoded</param>

+        public void AddEntriesFrom(CodedInputStream input, Codec codec)

+        {

+            var adapter = new Codec.MessageAdapter(codec);

+            do

+            {

+                adapter.Reset();

+                input.ReadMessage(adapter);

+                this[adapter.Key] = adapter.Value;

+            } while (input.MaybeConsumeTag(codec.MapTag));

+        }

+

+        /// <summary>

+        /// Writes the contents of this map to the given coded output stream, using the specified codec

+        /// to encode each entry.

+        /// </summary>

+        /// <param name="output">The output stream to write to.</param>

+        /// <param name="codec">The codec to use for each entry.</param>

+        public void WriteTo(CodedOutputStream output, Codec codec)

+        {

+            var message = new Codec.MessageAdapter(codec);

+            foreach (var entry in list)

+            {

+                message.Key = entry.Key;

+                message.Value = entry.Value;

+                output.WriteTag(codec.MapTag);

+                output.WriteMessage(message);

+            }

+        }

+

+        /// <summary>

+        /// Calculates the size of this map based on the given entry codec.

+        /// </summary>

+        /// <param name="codec">The codec to use to encode each entry.</param>

+        /// <returns></returns>

+        public int CalculateSize(Codec codec)

+        {

+            if (Count == 0)

+            {

+                return 0;

+            }

+            var message = new Codec.MessageAdapter(codec);

+            int size = 0;

+            foreach (var entry in list)

+            {

+                message.Key = entry.Key;

+                message.Value = entry.Value;

+                size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);

+                size += CodedOutputStream.ComputeMessageSize(message);

+            }

+            return size;

+        }

+

+        /// <summary>

+        /// Returns a string representation of this repeated field, in the same

+        /// way as it would be represented by the default JSON formatter.

+        /// </summary>

+        public override string ToString()

+        {

+            var writer = new StringWriter();

+            JsonFormatter.Default.WriteDictionary(writer, this);

+            return writer.ToString();

+        }

+

+        #region IDictionary explicit interface implementation

+        void IDictionary.Add(object key, object value)

+        {

+            Add((TKey)key, (TValue)value);

+        }

+

+        bool IDictionary.Contains(object key)

+        {

+            if (!(key is TKey))

+            {

+                return false;

+            }

+            return ContainsKey((TKey)key);

+        }

+

+        IDictionaryEnumerator IDictionary.GetEnumerator()

+        {

+            return new DictionaryEnumerator(GetEnumerator());

+        }

+

+        void IDictionary.Remove(object key)

+        {

+            ProtoPreconditions.CheckNotNull(key, nameof(key));

+            if (!(key is TKey))

+            {

+                return;

+            }

+            Remove((TKey)key);

+        }

+

+        void ICollection.CopyTo(Array array, int index)

+        {

+            // This is ugly and slow as heck, but with any luck it will never be used anyway.

+            ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key, pair.Value)).ToList();

+            temp.CopyTo(array, index);

+        }

+

+        bool IDictionary.IsFixedSize { get { return false; } }

+

+        ICollection IDictionary.Keys { get { return (ICollection)Keys; } }

+

+        ICollection IDictionary.Values { get { return (ICollection)Values; } }

+

+        bool ICollection.IsSynchronized { get { return false; } }

+

+        object ICollection.SyncRoot { get { return this; } }

+

+        object IDictionary.this[object key]

+        {

+            get

+            {

+                ProtoPreconditions.CheckNotNull(key, nameof(key));

+                if (!(key is TKey))

+                {

+                    return null;

+                }

+                TValue value;

+                TryGetValue((TKey)key, out value);

+                return value;

+            }

+

+            set

+            {

+                this[(TKey)key] = (TValue)value;

+            }

+        }

+        #endregion

+

+        #region IReadOnlyDictionary explicit interface implementation

+#if !NET35

+        IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;

+

+        IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;

+#endif

+        #endregion

+

+        private class DictionaryEnumerator : IDictionaryEnumerator

+        {

+            private readonly IEnumerator<KeyValuePair<TKey, TValue>> enumerator;

+

+            internal DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator)

+            {

+                this.enumerator = enumerator;

+            }

+

+            public bool MoveNext()

+            {

+                return enumerator.MoveNext();

+            }

+

+            public void Reset()

+            {

+                enumerator.Reset();

+            }

+

+            public object Current { get { return Entry; } }

+            public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }

+            public object Key { get { return enumerator.Current.Key; } }

+            public object Value { get { return enumerator.Current.Value; } }

+        }

+

+        /// <summary>

+        /// A codec for a specific map field. This contains all the information required to encode and

+        /// decode the nested messages.

+        /// </summary>

+        public sealed class Codec

+        {

+            private readonly FieldCodec<TKey> keyCodec;

+            private readonly FieldCodec<TValue> valueCodec;

+            private readonly uint mapTag;

+

+            /// <summary>

+            /// Creates a new entry codec based on a separate key codec and value codec,

+            /// and the tag to use for each map entry.

+            /// </summary>

+            /// <param name="keyCodec">The key codec.</param>

+            /// <param name="valueCodec">The value codec.</param>

+            /// <param name="mapTag">The map tag to use to introduce each map entry.</param>

+            public Codec(FieldCodec<TKey> keyCodec, FieldCodec<TValue> valueCodec, uint mapTag)

+            {

+                this.keyCodec = keyCodec;

+                this.valueCodec = valueCodec;

+                this.mapTag = mapTag;

+            }

+

+            /// <summary>

+            /// The tag used in the enclosing message to indicate map entries.

+            /// </summary>

+            internal uint MapTag { get { return mapTag; } }

+

+            /// <summary>

+            /// A mutable message class, used for parsing and serializing. This

+            /// delegates the work to a codec, but implements the <see cref="IMessage"/> interface

+            /// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.

+            /// This is nested inside Codec as it's tightly coupled to the associated codec,

+            /// and it's simpler if it has direct access to all its fields.

+            /// </summary>

+            internal class MessageAdapter : IMessage

+            {

+                private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };

+

+                private readonly Codec codec;

+                internal TKey Key { get; set; }

+                internal TValue Value { get; set; }

+

+                internal MessageAdapter(Codec codec)

+                {

+                    this.codec = codec;

+                }

+

+                internal void Reset()

+                {

+                    Key = codec.keyCodec.DefaultValue;

+                    Value = codec.valueCodec.DefaultValue;

+                }

+

+                public void MergeFrom(CodedInputStream input)

+                {

+                    uint tag;

+                    while ((tag = input.ReadTag()) != 0)

+                    {

+                        if (tag == codec.keyCodec.Tag)

+                        {

+                            Key = codec.keyCodec.Read(input);

+                        }

+                        else if (tag == codec.valueCodec.Tag)

+                        {

+                            Value = codec.valueCodec.Read(input);

+                        }

+                        else 

+                        {

+                            input.SkipLastField();

+                        }

+                    }

+

+                    // Corner case: a map entry with a key but no value, where the value type is a message.

+                    // Read it as if we'd seen an input stream with no data (i.e. create a "default" message).

+                    if (Value == null)

+                    {

+                        Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));

+                    }

+                }

+

+                public void WriteTo(CodedOutputStream output)

+                {

+                    codec.keyCodec.WriteTagAndValue(output, Key);

+                    codec.valueCodec.WriteTagAndValue(output, Value);

+                }

+

+                public int CalculateSize()

+                {

+                    return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);

+                }

+

+                MessageDescriptor IMessage.Descriptor { get { return null; } }

+            }

+        }

+

+        private class MapView<T> : ICollection<T>, ICollection

+        {

+            private readonly MapField<TKey, TValue> parent;

+            private readonly Func<KeyValuePair<TKey, TValue>, T> projection;

+            private readonly Func<T, bool> containsCheck;

+

+            internal MapView(

+                MapField<TKey, TValue> parent,

+                Func<KeyValuePair<TKey, TValue>, T> projection,

+                Func<T, bool> containsCheck)

+            {

+                this.parent = parent;

+                this.projection = projection;

+                this.containsCheck = containsCheck;

+            }

+

+            public int Count { get { return parent.Count; } }

+

+            public bool IsReadOnly { get { return true; } }

+

+            public bool IsSynchronized { get { return false; } }

+

+            public object SyncRoot { get { return parent; } }

+

+            public void Add(T item)

+            {

+                throw new NotSupportedException();

+            }

+

+            public void Clear()

+            {

+                throw new NotSupportedException();

+            }

+

+            public bool Contains(T item)

+            {

+                return containsCheck(item);

+            }

+

+            public void CopyTo(T[] array, int arrayIndex)

+            {

+                if (arrayIndex < 0)

+                {

+                    throw new ArgumentOutOfRangeException(nameof(arrayIndex));

+                }

+                if (arrayIndex + Count > array.Length)

+                {

+                    throw new ArgumentException("Not enough space in the array", nameof(array));

+                }

+                foreach (var item in this)

+                {

+                    array[arrayIndex++] = item;

+                }

+            }

+

+            public IEnumerator<T> GetEnumerator()

+            {

+                return parent.list.Select(projection).GetEnumerator();

+            }

+

+            public bool Remove(T item)

+            {

+                throw new NotSupportedException();

+            }

+

+            IEnumerator IEnumerable.GetEnumerator()

+            {

+                return GetEnumerator();

+            }

+

+            public void CopyTo(Array array, int index)

+            {

+                if (index < 0)

+                {

+                    throw new ArgumentOutOfRangeException(nameof(index));

+                }

+                if (index + Count > array.Length)

+                {

+                    throw new ArgumentException("Not enough space in the array", nameof(array));

+                }

+                foreach (var item in this)

+                {

+                    array.SetValue(item, index++);

+                }

+            }

+        }

+    }

+}

diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
index c18b63e..613ca9c 100644
--- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
+++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -1,595 +1,595 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2015 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-
-namespace Google.Protobuf.Collections
-{
-    /// <summary>
-    /// The contents of a repeated field: essentially, a collection with some extra
-    /// restrictions (no null values) and capabilities (deep cloning).
-    /// </summary>
-    /// <remarks>
-    /// This implementation does not generally prohibit the use of types which are not
-    /// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases.
-    /// </remarks>
-    /// <typeparam name="T">The element type of the repeated field.</typeparam>
-    public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>
-#if !NET35
-        , IReadOnlyList<T>
-#endif
-    {
-        private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();
-        private static readonly T[] EmptyArray = new T[0];
-        private const int MinArraySize = 8;
-
-        private T[] array = EmptyArray;
-        private int count = 0;
-
-        /// <summary>
-        /// Creates a deep clone of this repeated field.
-        /// </summary>
-        /// <remarks>
-        /// If the field type is
-        /// a message type, each element is also cloned; otherwise, it is
-        /// assumed that the field type is primitive (including string and
-        /// bytes, both of which are immutable) and so a simple copy is
-        /// equivalent to a deep clone.
-        /// </remarks>
-        /// <returns>A deep clone of this repeated field.</returns>
-        public RepeatedField<T> Clone()
-        {
-            RepeatedField<T> clone = new RepeatedField<T>();
-            if (array != EmptyArray)
-            {
-                clone.array = (T[])array.Clone();
-                IDeepCloneable<T>[] cloneableArray = clone.array as IDeepCloneable<T>[];
-                if (cloneableArray != null)
-                {
-                    for (int i = 0; i < count; i++)
-                    {
-                        clone.array[i] = cloneableArray[i].Clone();
-                    }
-                }
-            }
-            clone.count = count;
-            return clone;
-        }
-
-        /// <summary>
-        /// Adds the entries from the given input stream, decoding them with the specified codec.
-        /// </summary>
-        /// <param name="input">The input stream to read from.</param>
-        /// <param name="codec">The codec to use in order to read each entry.</param>
-        public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec)
-        {
-            // TODO: Inline some of the Add code, so we can avoid checking the size on every
-            // iteration.
-            uint tag = input.LastTag;
-            var reader = codec.ValueReader;
-            // Non-nullable value types can be packed or not.
-            if (FieldCodec<T>.IsPackedRepeatedField(tag))
-            {
-                int length = input.ReadLength();
-                if (length > 0)
-                {
-                    int oldLimit = input.PushLimit(length);
-                    while (!input.ReachedLimit)
-                    {
-                        Add(reader(input));
-                    }
-                    input.PopLimit(oldLimit);
-                }
-                // Empty packed field. Odd, but valid - just ignore.
-            }
-            else
-            {
-                // Not packed... (possibly not packable)
-                do
-                {
-                    Add(reader(input));
-                } while (input.MaybeConsumeTag(tag));
-            }
-        }
-
-        /// <summary>
-        /// Calculates the size of this collection based on the given codec.
-        /// </summary>
-        /// <param name="codec">The codec to use when encoding each field.</param>
-        /// <returns>The number of bytes that would be written to a <see cref="CodedOutputStream"/> by <see cref="WriteTo"/>,
-        /// using the same codec.</returns>
-        public int CalculateSize(FieldCodec<T> codec)
-        {
-            if (count == 0)
-            {
-                return 0;
-            }
-            uint tag = codec.Tag;
-            if (codec.PackedRepeatedField)
-            {
-                int dataSize = CalculatePackedDataSize(codec);
-                return CodedOutputStream.ComputeRawVarint32Size(tag) +
-                    CodedOutputStream.ComputeLengthSize(dataSize) +
-                    dataSize;
-            }
-            else
-            {
-                var sizeCalculator = codec.ValueSizeCalculator;
-                int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);
-                for (int i = 0; i < count; i++)
-                {
-                    size += sizeCalculator(array[i]);
-                }
-                return size;
-            }
-        }
-
-        private int CalculatePackedDataSize(FieldCodec<T> codec)
-        {
-            int fixedSize = codec.FixedSize;
-            if (fixedSize == 0)
-            {
-                var calculator = codec.ValueSizeCalculator;
-                int tmp = 0;
-                for (int i = 0; i < count; i++)
-                {
-                    tmp += calculator(array[i]);
-                }
-                return tmp;
-            }
-            else
-            {
-                return fixedSize * Count;
-            }
-        }
-
-        /// <summary>
-        /// Writes the contents of this collection to the given <see cref="CodedOutputStream"/>,
-        /// encoding each value using the specified codec.
-        /// </summary>
-        /// <param name="output">The output stream to write to.</param>
-        /// <param name="codec">The codec to use when encoding each value.</param>
-        public void WriteTo(CodedOutputStream output, FieldCodec<T> codec)
-        {
-            if (count == 0)
-            {
-                return;
-            }
-            var writer = codec.ValueWriter;
-            var tag = codec.Tag;
-            if (codec.PackedRepeatedField)
-            {
-                // Packed primitive type
-                uint size = (uint)CalculatePackedDataSize(codec);
-                output.WriteTag(tag);
-                output.WriteRawVarint32(size);
-                for (int i = 0; i < count; i++)
-                {
-                    writer(output, array[i]);
-                }
-            }
-            else
-            {
-                // Not packed: a simple tag/value pair for each value.
-                // Can't use codec.WriteTagAndValue, as that omits default values.
-                for (int i = 0; i < count; i++)
-                {
-                    output.WriteTag(tag);
-                    writer(output, array[i]);
-                }
-            }
-        }
-
-        private void EnsureSize(int size)
-        {
-            if (array.Length < size)
-            {
-                size = Math.Max(size, MinArraySize);
-                int newSize = Math.Max(array.Length * 2, size);
-                var tmp = new T[newSize];
-                Array.Copy(array, 0, tmp, 0, array.Length);
-                array = tmp;
-            }
-        }
-
-        /// <summary>
-        /// Adds the specified item to the collection.
-        /// </summary>
-        /// <param name="item">The item to add.</param>
-        public void Add(T item)
-        {
-            ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
-            EnsureSize(count + 1);
-            array[count++] = item;
-        }
-
-        /// <summary>
-        /// Removes all items from the collection.
-        /// </summary>
-        public void Clear()
-        {
-            array = EmptyArray;
-            count = 0;
-        }
-
-        /// <summary>
-        /// Determines whether this collection contains the given item.
-        /// </summary>
-        /// <param name="item">The item to find.</param>
-        /// <returns><c>true</c> if this collection contains the given item; <c>false</c> otherwise.</returns>
-        public bool Contains(T item)
-        {
-            return IndexOf(item) != -1;
-        }
-
-        /// <summary>
-        /// Copies this collection to the given array.
-        /// </summary>
-        /// <param name="array">The array to copy to.</param>
-        /// <param name="arrayIndex">The first index of the array to copy to.</param>
-        public void CopyTo(T[] array, int arrayIndex)
-        {
-            Array.Copy(this.array, 0, array, arrayIndex, count);
-        }
-
-        /// <summary>
-        /// Removes the specified item from the collection
-        /// </summary>
-        /// <param name="item">The item to remove.</param>
-        /// <returns><c>true</c> if the item was found and removed; <c>false</c> otherwise.</returns>
-        public bool Remove(T item)
-        {
-            int index = IndexOf(item);
-            if (index == -1)
-            {
-                return false;
-            }            
-            Array.Copy(array, index + 1, array, index, count - index - 1);
-            count--;
-            array[count] = default(T);
-            return true;
-        }
-
-        /// <summary>
-        /// Gets the number of elements contained in the collection.
-        /// </summary>
-        public int Count => count;
-
-        /// <summary>
-        /// Gets a value indicating whether the collection is read-only.
-        /// </summary>
-        public bool IsReadOnly => false;
-
-        /// <summary>
-        /// Adds all of the specified values into this collection.
-        /// </summary>
-        /// <param name="values">The values to add to this collection.</param>
-        public void AddRange(IEnumerable<T> values)
-        {
-            ProtoPreconditions.CheckNotNull(values, nameof(values));
-
-            // Optimization 1: If the collection we're adding is already a RepeatedField<T>,
-            // we know the values are valid.
-            var otherRepeatedField = values as RepeatedField<T>;
-            if (otherRepeatedField != null)
-            {
-                EnsureSize(count + otherRepeatedField.count);
-                Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count);
-                count += otherRepeatedField.count;
-                return;
-            }
-
-            // Optimization 2: The collection is an ICollection, so we can expand
-            // just once and ask the collection to copy itself into the array.
-            var collection = values as ICollection;
-            if (collection != null)
-            {
-                var extraCount = collection.Count;
-                // For reference types and nullable value types, we need to check that there are no nulls
-                // present. (This isn't a thread-safe approach, but we don't advertise this is thread-safe.)
-                // We expect the JITter to optimize this test to true/false, so it's effectively conditional
-                // specialization.
-                if (default(T) == null)
-                {
-                    // TODO: Measure whether iterating once to check and then letting the collection copy
-                    // itself is faster or slower than iterating and adding as we go. For large
-                    // collections this will not be great in terms of cache usage... but the optimized
-                    // copy may be significantly faster than doing it one at a time.
-                    foreach (var item in collection)
-                    {
-                        if (item == null)
-                        {
-                            throw new ArgumentException("Sequence contained null element", nameof(values));
-                        }
-                    }
-                }
-                EnsureSize(count + extraCount);
-                collection.CopyTo(array, count);
-                count += extraCount;
-                return;
-            }
-
-            // We *could* check for ICollection<T> as well, but very very few collections implement
-            // ICollection<T> but not ICollection. (HashSet<T> does, for one...)
-
-            // Fall back to a slower path of adding items one at a time.
-            foreach (T item in values)
-            {
-                Add(item);
-            }
-        }
-
-        /// <summary>
-        /// Adds all of the specified values into this collection. This method is present to
-        /// allow repeated fields to be constructed from queries within collection initializers.
-        /// Within non-collection-initializer code, consider using the equivalent <see cref="AddRange"/>
-        /// method instead for clarity.
-        /// </summary>
-        /// <param name="values">The values to add to this collection.</param>
-        public void Add(IEnumerable<T> values)
-        {
-            AddRange(values);
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through the collection.
-        /// </summary>
-        /// <returns>
-        /// An enumerator that can be used to iterate through the collection.
-        /// </returns>
-        public IEnumerator<T> GetEnumerator()
-        {
-            for (int i = 0; i < count; i++)
-            {
-                yield return array[i];
-            }
-        }
-
-        /// <summary>
-        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
-        /// </summary>
-        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
-        /// <returns>
-        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
-        /// </returns>
-        public override bool Equals(object obj)
-        {
-            return Equals(obj as RepeatedField<T>);
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through a collection.
-        /// </summary>
-        /// <returns>
-        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
-        /// </returns>
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
-
-        /// <summary>
-        /// Returns a hash code for this instance.
-        /// </summary>
-        /// <returns>
-        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
-        /// </returns>
-        public override int GetHashCode()
-        {
-            int hash = 0;
-            for (int i = 0; i < count; i++)
-            {
-                hash = hash * 31 + array[i].GetHashCode();
-            }
-            return hash;
-        }
-
-        /// <summary>
-        /// Compares this repeated field with another for equality.
-        /// </summary>
-        /// <param name="other">The repeated field to compare this with.</param>
-        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal repeated field; <c>false</c> otherwise.</returns>
-        public bool Equals(RepeatedField<T> other)
-        {
-            if (ReferenceEquals(other, null))
-            {
-                return false;
-            }
-            if (ReferenceEquals(other, this))
-            {
-                return true;
-            }
-            if (other.Count != this.Count)
-            {
-                return false;
-            }
-            EqualityComparer<T> comparer = EqualityComparer;
-            for (int i = 0; i < count; i++)
-            {
-                if (!comparer.Equals(array[i], other.array[i]))
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        /// <summary>
-        /// Returns the index of the given item within the collection, or -1 if the item is not
-        /// present.
-        /// </summary>
-        /// <param name="item">The item to find in the collection.</param>
-        /// <returns>The zero-based index of the item, or -1 if it is not found.</returns>
-        public int IndexOf(T item)
-        {
-            ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
-            EqualityComparer<T> comparer = EqualityComparer;
-            for (int i = 0; i < count; i++)
-            {
-                if (comparer.Equals(array[i], item))
-                {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Inserts the given item at the specified index.
-        /// </summary>
-        /// <param name="index">The index at which to insert the item.</param>
-        /// <param name="item">The item to insert.</param>
-        public void Insert(int index, T item)
-        {
-            ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));
-            if (index < 0 || index > count)
-            {
-                throw new ArgumentOutOfRangeException(nameof(index));
-            }
-            EnsureSize(count + 1);
-            Array.Copy(array, index, array, index + 1, count - index);
-            array[index] = item;
-            count++;
-        }
-
-        /// <summary>
-        /// Removes the item at the given index.
-        /// </summary>
-        /// <param name="index">The zero-based index of the item to remove.</param>
-        public void RemoveAt(int index)
-        {
-            if (index < 0 || index >= count)
-            {
-                throw new ArgumentOutOfRangeException(nameof(index));
-            }
-            Array.Copy(array, index + 1, array, index, count - index - 1);
-            count--;
-            array[count] = default(T);
-        }
-
-        /// <summary>
-        /// Returns a string representation of this repeated field, in the same
-        /// way as it would be represented by the default JSON formatter.
-        /// </summary>
-        public override string ToString()
-        {
-            var writer = new StringWriter();
-            JsonFormatter.Default.WriteList(writer, this);
-            return writer.ToString();
-        }
-
-        /// <summary>
-        /// Gets or sets the item at the specified index.
-        /// </summary>
-        /// <value>
-        /// The element at the specified index.
-        /// </value>
-        /// <param name="index">The zero-based index of the element to get or set.</param>
-        /// <returns>The item at the specified index.</returns>
-        public T this[int index]
-        {
-            get
-            {
-                if (index < 0 || index >= count)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(index));
-                }
-                return array[index];
-            }
-            set
-            {
-                if (index < 0 || index >= count)
-                {
-                    throw new ArgumentOutOfRangeException(nameof(index));
-                }
-                ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
-                array[index] = value;
-            }
-        }
-
-        #region Explicit interface implementation for IList and ICollection.
-        bool IList.IsFixedSize => false;
-
-        void ICollection.CopyTo(Array array, int index)
-        {
-            Array.Copy(this.array, 0, array, index, count);
-        }
-
-        bool ICollection.IsSynchronized => false;
-
-        object ICollection.SyncRoot => this;
-
-        object IList.this[int index]
-        {
-            get { return this[index]; }
-            set { this[index] = (T)value; }
-        }
-
-        int IList.Add(object value)
-        {
-            Add((T) value);
-            return count - 1;
-        }
-
-        bool IList.Contains(object value)
-        {
-            return (value is T && Contains((T)value));
-        }
-
-        int IList.IndexOf(object value)
-        {
-            if (!(value is T))
-            {
-                return -1;
-            }
-            return IndexOf((T)value);
-        }
-
-        void IList.Insert(int index, object value)
-        {
-            Insert(index, (T) value);
-        }
-
-        void IList.Remove(object value)
-        {
-            if (!(value is T))
-            {
-                return;
-            }
-            Remove((T)value);
-        }
-        #endregion        
-    }
-}
+#region Copyright notice and license

+// Protocol Buffers - Google's data interchange format

+// Copyright 2015 Google Inc.  All rights reserved.

+// https://developers.google.com/protocol-buffers/

+//

+// Redistribution and use in source and binary forms, with or without

+// modification, are permitted provided that the following conditions are

+// met:

+//

+//     * Redistributions of source code must retain the above copyright

+// notice, this list of conditions and the following disclaimer.

+//     * Redistributions in binary form must reproduce the above

+// copyright notice, this list of conditions and the following disclaimer

+// in the documentation and/or other materials provided with the

+// distribution.

+//     * Neither the name of Google Inc. nor the names of its

+// contributors may be used to endorse or promote products derived from

+// this software without specific prior written permission.

+//

+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#endregion

+

+using System;

+using System.Collections;

+using System.Collections.Generic;

+using System.IO;

+

+namespace Google.Protobuf.Collections

+{

+    /// <summary>

+    /// The contents of a repeated field: essentially, a collection with some extra

+    /// restrictions (no null values) and capabilities (deep cloning).

+    /// </summary>

+    /// <remarks>

+    /// This implementation does not generally prohibit the use of types which are not

+    /// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases.

+    /// </remarks>

+    /// <typeparam name="T">The element type of the repeated field.</typeparam>

+    public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>

+#if !NET35

+        , IReadOnlyList<T>

+#endif

+    {

+        private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();

+        private static readonly T[] EmptyArray = new T[0];

+        private const int MinArraySize = 8;

+

+        private T[] array = EmptyArray;

+        private int count = 0;

+

+        /// <summary>

+        /// Creates a deep clone of this repeated field.

+        /// </summary>

+        /// <remarks>

+        /// If the field type is

+        /// a message type, each element is also cloned; otherwise, it is

+        /// assumed that the field type is primitive (including string and

+        /// bytes, both of which are immutable) and so a simple copy is

+        /// equivalent to a deep clone.

+        /// </remarks>

+        /// <returns>A deep clone of this repeated field.</returns>

+        public RepeatedField<T> Clone()

+        {

+            RepeatedField<T> clone = new RepeatedField<T>();

+            if (array != EmptyArray)

+            {

+                clone.array = (T[])array.Clone();

+                IDeepCloneable<T>[] cloneableArray = clone.array as IDeepCloneable<T>[];

+                if (cloneableArray != null)

+                {

+                    for (int i = 0; i < count; i++)

+                    {

+                        clone.array[i] = cloneableArray[i].Clone();

+                    }

+                }

+            }

+            clone.count = count;

+            return clone;

+        }

+

+        /// <summary>

+        /// Adds the entries from the given input stream, decoding them with the specified codec.

+        /// </summary>

+        /// <param name="input">The input stream to read from.</param>

+        /// <param name="codec">The codec to use in order to read each entry.</param>

+        public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec)

+        {

+            // TODO: Inline some of the Add code, so we can avoid checking the size on every

+            // iteration.

+            uint tag = input.LastTag;

+            var reader = codec.ValueReader;

+            // Non-nullable value types can be packed or not.

+            if (FieldCodec<T>.IsPackedRepeatedField(tag))

+            {

+                int length = input.ReadLength();

+                if (length > 0)

+                {

+                    int oldLimit = input.PushLimit(length);

+                    while (!input.ReachedLimit)

+                    {

+                        Add(reader(input));

+                    }

+                    input.PopLimit(oldLimit);

+                }

+                // Empty packed field. Odd, but valid - just ignore.

+            }

+            else

+            {

+                // Not packed... (possibly not packable)

+                do

+                {

+                    Add(reader(input));

+                } while (input.MaybeConsumeTag(tag));

+            }

+        }

+

+        /// <summary>

+        /// Calculates the size of this collection based on the given codec.

+        /// </summary>

+        /// <param name="codec">The codec to use when encoding each field.</param>

+        /// <returns>The number of bytes that would be written to a <see cref="CodedOutputStream"/> by <see cref="WriteTo"/>,

+        /// using the same codec.</returns>

+        public int CalculateSize(FieldCodec<T> codec)

+        {

+            if (count == 0)

+            {

+                return 0;

+            }

+            uint tag = codec.Tag;

+            if (codec.PackedRepeatedField)

+            {

+                int dataSize = CalculatePackedDataSize(codec);

+                return CodedOutputStream.ComputeRawVarint32Size(tag) +

+                    CodedOutputStream.ComputeLengthSize(dataSize) +

+                    dataSize;

+            }

+            else

+            {

+                var sizeCalculator = codec.ValueSizeCalculator;

+                int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);

+                for (int i = 0; i < count; i++)

+                {

+                    size += sizeCalculator(array[i]);

+                }

+                return size;

+            }

+        }

+

+        private int CalculatePackedDataSize(FieldCodec<T> codec)

+        {

+            int fixedSize = codec.FixedSize;

+            if (fixedSize == 0)

+            {

+                var calculator = codec.ValueSizeCalculator;

+                int tmp = 0;

+                for (int i = 0; i < count; i++)

+                {

+                    tmp += calculator(array[i]);

+                }

+                return tmp;

+            }

+            else

+            {

+                return fixedSize * Count;

+            }

+        }

+

+        /// <summary>

+        /// Writes the contents of this collection to the given <see cref="CodedOutputStream"/>,

+        /// encoding each value using the specified codec.

+        /// </summary>

+        /// <param name="output">The output stream to write to.</param>

+        /// <param name="codec">The codec to use when encoding each value.</param>

+        public void WriteTo(CodedOutputStream output, FieldCodec<T> codec)

+        {

+            if (count == 0)

+            {

+                return;

+            }

+            var writer = codec.ValueWriter;

+            var tag = codec.Tag;

+            if (codec.PackedRepeatedField)

+            {

+                // Packed primitive type

+                uint size = (uint)CalculatePackedDataSize(codec);

+                output.WriteTag(tag);

+                output.WriteRawVarint32(size);

+                for (int i = 0; i < count; i++)

+                {

+                    writer(output, array[i]);

+                }

+            }

+            else

+            {

+                // Not packed: a simple tag/value pair for each value.

+                // Can't use codec.WriteTagAndValue, as that omits default values.

+                for (int i = 0; i < count; i++)

+                {

+                    output.WriteTag(tag);

+                    writer(output, array[i]);

+                }

+            }

+        }

+

+        private void EnsureSize(int size)

+        {

+            if (array.Length < size)

+            {

+                size = Math.Max(size, MinArraySize);

+                int newSize = Math.Max(array.Length * 2, size);

+                var tmp = new T[newSize];

+                Array.Copy(array, 0, tmp, 0, array.Length);

+                array = tmp;

+            }

+        }

+

+        /// <summary>

+        /// Adds the specified item to the collection.

+        /// </summary>

+        /// <param name="item">The item to add.</param>

+        public void Add(T item)

+        {

+            ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));

+            EnsureSize(count + 1);

+            array[count++] = item;

+        }

+

+        /// <summary>

+        /// Removes all items from the collection.

+        /// </summary>

+        public void Clear()

+        {

+            array = EmptyArray;

+            count = 0;

+        }

+

+        /// <summary>

+        /// Determines whether this collection contains the given item.

+        /// </summary>

+        /// <param name="item">The item to find.</param>

+        /// <returns><c>true</c> if this collection contains the given item; <c>false</c> otherwise.</returns>

+        public bool Contains(T item)

+        {

+            return IndexOf(item) != -1;

+        }

+

+        /// <summary>

+        /// Copies this collection to the given array.

+        /// </summary>

+        /// <param name="array">The array to copy to.</param>

+        /// <param name="arrayIndex">The first index of the array to copy to.</param>

+        public void CopyTo(T[] array, int arrayIndex)

+        {

+            Array.Copy(this.array, 0, array, arrayIndex, count);

+        }

+

+        /// <summary>

+        /// Removes the specified item from the collection

+        /// </summary>

+        /// <param name="item">The item to remove.</param>

+        /// <returns><c>true</c> if the item was found and removed; <c>false</c> otherwise.</returns>

+        public bool Remove(T item)

+        {

+            int index = IndexOf(item);

+            if (index == -1)

+            {

+                return false;

+            }            

+            Array.Copy(array, index + 1, array, index, count - index - 1);

+            count--;

+            array[count] = default(T);

+            return true;

+        }

+

+        /// <summary>

+        /// Gets the number of elements contained in the collection.

+        /// </summary>

+        public int Count => count;

+

+        /// <summary>

+        /// Gets a value indicating whether the collection is read-only.

+        /// </summary>

+        public bool IsReadOnly => false;

+

+        /// <summary>

+        /// Adds all of the specified values into this collection.

+        /// </summary>

+        /// <param name="values">The values to add to this collection.</param>

+        public void AddRange(IEnumerable<T> values)

+        {

+            ProtoPreconditions.CheckNotNull(values, nameof(values));

+

+            // Optimization 1: If the collection we're adding is already a RepeatedField<T>,

+            // we know the values are valid.

+            var otherRepeatedField = values as RepeatedField<T>;

+            if (otherRepeatedField != null)

+            {

+                EnsureSize(count + otherRepeatedField.count);

+                Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count);

+                count += otherRepeatedField.count;

+                return;

+            }

+

+            // Optimization 2: The collection is an ICollection, so we can expand

+            // just once and ask the collection to copy itself into the array.

+            var collection = values as ICollection;

+            if (collection != null)

+            {

+                var extraCount = collection.Count;

+                // For reference types and nullable value types, we need to check that there are no nulls

+                // present. (This isn't a thread-safe approach, but we don't advertise this is thread-safe.)

+                // We expect the JITter to optimize this test to true/false, so it's effectively conditional

+                // specialization.

+                if (default(T) == null)

+                {

+                    // TODO: Measure whether iterating once to check and then letting the collection copy

+                    // itself is faster or slower than iterating and adding as we go. For large

+                    // collections this will not be great in terms of cache usage... but the optimized

+                    // copy may be significantly faster than doing it one at a time.

+                    foreach (var item in collection)

+                    {

+                        if (item == null)

+                        {

+                            throw new ArgumentException("Sequence contained null element", nameof(values));

+                        }

+                    }

+                }

+                EnsureSize(count + extraCount);

+                collection.CopyTo(array, count);

+                count += extraCount;

+                return;

+            }

+

+            // We *could* check for ICollection<T> as well, but very very few collections implement

+            // ICollection<T> but not ICollection. (HashSet<T> does, for one...)

+

+            // Fall back to a slower path of adding items one at a time.

+            foreach (T item in values)

+            {

+                Add(item);

+            }

+        }

+

+        /// <summary>

+        /// Adds all of the specified values into this collection. This method is present to

+        /// allow repeated fields to be constructed from queries within collection initializers.

+        /// Within non-collection-initializer code, consider using the equivalent <see cref="AddRange"/>

+        /// method instead for clarity.

+        /// </summary>

+        /// <param name="values">The values to add to this collection.</param>

+        public void Add(IEnumerable<T> values)

+        {

+            AddRange(values);

+        }

+

+        /// <summary>

+        /// Returns an enumerator that iterates through the collection.

+        /// </summary>

+        /// <returns>

+        /// An enumerator that can be used to iterate through the collection.

+        /// </returns>

+        public IEnumerator<T> GetEnumerator()

+        {

+            for (int i = 0; i < count; i++)

+            {

+                yield return array[i];

+            }

+        }

+

+        /// <summary>

+        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.

+        /// </summary>

+        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>

+        /// <returns>

+        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.

+        /// </returns>

+        public override bool Equals(object obj)

+        {

+            return Equals(obj as RepeatedField<T>);

+        }

+

+        /// <summary>

+        /// Returns an enumerator that iterates through a collection.

+        /// </summary>

+        /// <returns>

+        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.

+        /// </returns>

+        IEnumerator IEnumerable.GetEnumerator()

+        {

+            return GetEnumerator();

+        }

+

+        /// <summary>

+        /// Returns a hash code for this instance.

+        /// </summary>

+        /// <returns>

+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 

+        /// </returns>

+        public override int GetHashCode()

+        {

+            int hash = 0;

+            for (int i = 0; i < count; i++)

+            {

+                hash = hash * 31 + array[i].GetHashCode();

+            }

+            return hash;

+        }

+

+        /// <summary>

+        /// Compares this repeated field with another for equality.

+        /// </summary>

+        /// <param name="other">The repeated field to compare this with.</param>

+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal repeated field; <c>false</c> otherwise.</returns>

+        public bool Equals(RepeatedField<T> other)

+        {

+            if (ReferenceEquals(other, null))

+            {

+                return false;

+            }

+            if (ReferenceEquals(other, this))

+            {

+                return true;

+            }

+            if (other.Count != this.Count)

+            {

+                return false;

+            }

+            EqualityComparer<T> comparer = EqualityComparer;

+            for (int i = 0; i < count; i++)

+            {

+                if (!comparer.Equals(array[i], other.array[i]))

+                {

+                    return false;

+                }

+            }

+            return true;

+        }

+

+        /// <summary>

+        /// Returns the index of the given item within the collection, or -1 if the item is not

+        /// present.

+        /// </summary>

+        /// <param name="item">The item to find in the collection.</param>

+        /// <returns>The zero-based index of the item, or -1 if it is not found.</returns>

+        public int IndexOf(T item)

+        {

+            ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));

+            EqualityComparer<T> comparer = EqualityComparer;

+            for (int i = 0; i < count; i++)

+            {

+                if (comparer.Equals(array[i], item))

+                {

+                    return i;

+                }

+            }

+            return -1;

+        }

+

+        /// <summary>

+        /// Inserts the given item at the specified index.

+        /// </summary>

+        /// <param name="index">The index at which to insert the item.</param>

+        /// <param name="item">The item to insert.</param>

+        public void Insert(int index, T item)

+        {

+            ProtoPreconditions.CheckNotNullUnconstrained(item, nameof(item));

+            if (index < 0 || index > count)

+            {

+                throw new ArgumentOutOfRangeException(nameof(index));

+            }

+            EnsureSize(count + 1);

+            Array.Copy(array, index, array, index + 1, count - index);

+            array[index] = item;

+            count++;

+        }

+

+        /// <summary>

+        /// Removes the item at the given index.

+        /// </summary>

+        /// <param name="index">The zero-based index of the item to remove.</param>

+        public void RemoveAt(int index)

+        {

+            if (index < 0 || index >= count)

+            {

+                throw new ArgumentOutOfRangeException(nameof(index));

+            }

+            Array.Copy(array, index + 1, array, index, count - index - 1);

+            count--;

+            array[count] = default(T);

+        }

+

+        /// <summary>

+        /// Returns a string representation of this repeated field, in the same

+        /// way as it would be represented by the default JSON formatter.

+        /// </summary>

+        public override string ToString()

+        {

+            var writer = new StringWriter();

+            JsonFormatter.Default.WriteList(writer, this);

+            return writer.ToString();

+        }

+

+        /// <summary>

+        /// Gets or sets the item at the specified index.

+        /// </summary>

+        /// <value>

+        /// The element at the specified index.

+        /// </value>

+        /// <param name="index">The zero-based index of the element to get or set.</param>

+        /// <returns>The item at the specified index.</returns>

+        public T this[int index]

+        {

+            get

+            {

+                if (index < 0 || index >= count)

+                {

+                    throw new ArgumentOutOfRangeException(nameof(index));

+                }

+                return array[index];

+            }

+            set

+            {

+                if (index < 0 || index >= count)

+                {

+                    throw new ArgumentOutOfRangeException(nameof(index));

+                }

+                ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));

+                array[index] = value;

+            }

+        }

+

+        #region Explicit interface implementation for IList and ICollection.

+        bool IList.IsFixedSize => false;

+

+        void ICollection.CopyTo(Array array, int index)

+        {

+            Array.Copy(this.array, 0, array, index, count);

+        }

+

+        bool ICollection.IsSynchronized => false;

+

+        object ICollection.SyncRoot => this;

+

+        object IList.this[int index]

+        {

+            get { return this[index]; }

+            set { this[index] = (T)value; }

+        }

+

+        int IList.Add(object value)

+        {

+            Add((T) value);

+            return count - 1;

+        }

+

+        bool IList.Contains(object value)

+        {

+            return (value is T && Contains((T)value));

+        }

+

+        int IList.IndexOf(object value)

+        {

+            if (!(value is T))

+            {

+                return -1;

+            }

+            return IndexOf((T)value);

+        }

+

+        void IList.Insert(int index, object value)

+        {

+            Insert(index, (T) value);

+        }

+

+        void IList.Remove(object value)

+        {

+            if (!(value is T))

+            {

+                return;

+            }

+            Remove((T)value);

+        }

+        #endregion        

+    }

+}

diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
index 0fbc530..27a97a0 100644
--- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
+++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
@@ -125,5 +125,10 @@
             return new InvalidProtocolBufferException(

                 "Stream of protocol messages had invalid tag. Expected tag is length-delimited field 1.");

         }

-    }

+

+        internal static InvalidProtocolBufferException MissingFields()

+        {

+            return new InvalidProtocolBufferException("Message was missing required fields");

+        }

+}

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs
index 62181eb..e1c57dc 100644
--- a/csharp/src/Google.Protobuf/MessageExtensions.cs
+++ b/csharp/src/Google.Protobuf/MessageExtensions.cs
@@ -30,7 +30,10 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
+using Google.Protobuf.Reflection;
+using System.Collections;
 using System.IO;
+using System.Linq;
 
 namespace Google.Protobuf
 {
@@ -140,6 +143,53 @@
             return ByteString.AttachBytes(message.ToByteArray());
         }
 
+        /// <summary>
+        /// Checks if all required fields in a message have values set. For proto3 messages, this returns true
+        /// </summary>
+        public static bool IsInitialized(this IMessage message)
+        {
+            if (message.Descriptor.File.Proto.Syntax != "proto2")
+            {
+                return true;
+            }
+
+            return message.Descriptor
+                .Fields
+                .InDeclarationOrder()
+                .All(f =>
+                {
+                    if (f.IsMap)
+                    {
+                        var map = (IDictionary)f.Accessor.GetValue(message);
+                        return map.Values.OfType<IMessage>().All(IsInitialized);
+                    }
+                    else if (f.IsRepeated && f.MessageType != null)
+                    {
+                        var enumerable = (IEnumerable)f.Accessor.GetValue(message);
+                        return enumerable.Cast<IMessage>().All(IsInitialized);
+                    }
+                    else if (f.MessageType != null)
+                    {
+                        if (f.Accessor.HasValue(message))
+                        {
+                            return ((IMessage)f.Accessor.GetValue(message)).IsInitialized();
+                        }
+                        else
+                        {
+                            return !f.IsRequired;
+                        }
+                    }
+                    else if (f.IsRequired)
+                    {
+                        return f.Accessor.HasValue(message);
+                    }
+                    else 
+                    {
+                        return true;
+                    }
+                });
+        }
+
         // Implementations allowing unknown fields to be discarded.
         internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields)
         {
diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs
index 4d35554..d3fa6cb 100644
--- a/csharp/src/Google.Protobuf/MessageParser.cs
+++ b/csharp/src/Google.Protobuf/MessageParser.cs
@@ -69,6 +69,7 @@
         {
             IMessage message = factory();
             message.MergeFrom(data, DiscardUnknownFields);
+            CheckMergedRequiredFields(message);
             return message;
         }
 
@@ -83,6 +84,7 @@
         {
             IMessage message = factory();
             message.MergeFrom(data, offset, length, DiscardUnknownFields);
+            CheckMergedRequiredFields(message);
             return message;
         }
 
@@ -95,6 +97,7 @@
         {
             IMessage message = factory();
             message.MergeFrom(data, DiscardUnknownFields);
+            CheckMergedRequiredFields(message);
             return message;
         }
 
@@ -107,6 +110,7 @@
         {
             IMessage message = factory();
             message.MergeFrom(input, DiscardUnknownFields);
+            CheckMergedRequiredFields(message);
             return message;
         }
 
@@ -123,6 +127,7 @@
         {
             IMessage message = factory();
             message.MergeDelimitedFrom(input, DiscardUnknownFields);
+            CheckMergedRequiredFields(message);
             return message;
         }
 
@@ -135,6 +140,7 @@
         {
             IMessage message = factory();
             MergeFrom(message, input);
+            CheckMergedRequiredFields(message);
             return message;
         }
 
@@ -167,6 +173,12 @@
             }
         }
 
+        internal static void CheckMergedRequiredFields(IMessage message)
+        {
+            if (!message.IsInitialized())
+                throw new InvalidOperationException("Parsed message does not contain all required fields");
+        }
+
         /// <summary>
         /// Creates a new message parser which optionally discards unknown fields when parsing.
         /// </summary>
diff --git a/csharp/src/Google.Protobuf/ProtoPreconditions.cs b/csharp/src/Google.Protobuf/ProtoPreconditions.cs
index abaeb9b..590a3bb 100644
--- a/csharp/src/Google.Protobuf/ProtoPreconditions.cs
+++ b/csharp/src/Google.Protobuf/ProtoPreconditions.cs
@@ -1,79 +1,79 @@
-#region Copyright notice and license
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-
-namespace Google.Protobuf
-{
-    /// <summary>
-    /// Helper methods for throwing exceptions when preconditions are not met.
-    /// </summary>
-    /// <remarks>
-    /// This class is used internally and by generated code; it is not particularly
-    /// expected to be used from application code, although nothing prevents it
-    /// from being used that way.
-    /// </remarks>
-    public static class ProtoPreconditions
-    {
-        /// <summary>
-        /// Throws an ArgumentNullException if the given value is null, otherwise
-        /// return the value to the caller.
-        /// </summary>
-        public static T CheckNotNull<T>(T value, string name) where T : class
-        {
-            if (value == null)
-            {
-                throw new ArgumentNullException(name);
-            }
-            return value;
-        }
-
-        /// <summary>
-        /// Throws an ArgumentNullException if the given value is null, otherwise
-        /// return the value to the caller.
-        /// </summary>
-        /// <remarks>
-        /// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter
-        /// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull
-        /// with a value type - but it gets in the way if either you want to use it with a nullable
-        /// value type, or you want to use it with an unconstrained type parameter.
-        /// </remarks>
-        internal static T CheckNotNullUnconstrained<T>(T value, string name)
-        {
-            if (value == null)
-            {
-                throw new ArgumentNullException(name);
-            }
-            return value;
-        }
-    }
+#region Copyright notice and license

+// Protocol Buffers - Google's data interchange format

+// Copyright 2008 Google Inc.  All rights reserved.

+// https://developers.google.com/protocol-buffers/

+//

+// Redistribution and use in source and binary forms, with or without

+// modification, are permitted provided that the following conditions are

+// met:

+//

+//     * Redistributions of source code must retain the above copyright

+// notice, this list of conditions and the following disclaimer.

+//     * Redistributions in binary form must reproduce the above

+// copyright notice, this list of conditions and the following disclaimer

+// in the documentation and/or other materials provided with the

+// distribution.

+//     * Neither the name of Google Inc. nor the names of its

+// contributors may be used to endorse or promote products derived from

+// this software without specific prior written permission.

+//

+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#endregion

+

+using System;

+

+namespace Google.Protobuf

+{

+    /// <summary>

+    /// Helper methods for throwing exceptions when preconditions are not met.

+    /// </summary>

+    /// <remarks>

+    /// This class is used internally and by generated code; it is not particularly

+    /// expected to be used from application code, although nothing prevents it

+    /// from being used that way.

+    /// </remarks>

+    public static class ProtoPreconditions

+    {

+        /// <summary>

+        /// Throws an ArgumentNullException if the given value is null, otherwise

+        /// return the value to the caller.

+        /// </summary>

+        public static T CheckNotNull<T>(T value, string name) where T : class

+        {

+            if (value == null)

+            {

+                throw new ArgumentNullException(name);

+            }

+            return value;

+        }

+

+        /// <summary>

+        /// Throws an ArgumentNullException if the given value is null, otherwise

+        /// return the value to the caller.

+        /// </summary>

+        /// <remarks>

+        /// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter

+        /// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull

+        /// with a value type - but it gets in the way if either you want to use it with a nullable

+        /// value type, or you want to use it with an unconstrained type parameter.

+        /// </remarks>

+        internal static T CheckNotNullUnconstrained<T>(T value, string name)

+        {

+            if (value == null)

+            {

+                throw new ArgumentNullException(name);

+            }

+            return value;

+        }

+    }

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
index 4cbed33..0c33e63 100644
--- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
@@ -351,8 +351,8 @@
       enumType_ = other.enumType_.Clone();
       service_ = other.service_.Clone();
       extension_ = other.extension_.Clone();
-      options_ = other.options_ != null ? other.options_.Clone() : null;
-      sourceCodeInfo_ = other.sourceCodeInfo_ != null ? other.sourceCodeInfo_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
+      sourceCodeInfo_ = other.HasSourceCodeInfo ? other.sourceCodeInfo_.Clone() : null;
       syntax_ = other.syntax_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
@@ -364,31 +364,55 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     /// <summary>
     /// file name, relative to root of source tree
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "package" field.</summary>
     public const int PackageFieldNumber = 2;
-    private string package_ = "";
+    private readonly static string PackageDefaultValue = "";
+
+    private string package_;
     /// <summary>
     /// e.g. "foo", "foo.bar", etc.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Package {
-      get { return package_; }
+      get { return package_ ?? PackageDefaultValue; }
       set {
         package_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "package" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPackage {
+      get { return package_ != null; }
+    }
+    /// <summary>Clears the value of the "package" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPackage() {
+      package_ = null;
+    }
 
     /// <summary>Field number for the "dependency" field.</summary>
     public const int DependencyFieldNumber = 3;
@@ -483,6 +507,16 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     /// <summary>Field number for the "source_code_info" field.</summary>
     public const int SourceCodeInfoFieldNumber = 9;
@@ -500,21 +534,43 @@
         sourceCodeInfo_ = value;
       }
     }
+    /// <summary>Gets whether the source_code_info field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasSourceCodeInfo {
+      get { return sourceCodeInfo_ != null; }
+    }
+    /// <summary>Clears the value of the source_code_info field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearSourceCodeInfo() {
+      sourceCodeInfo_ = null;
+    }
 
     /// <summary>Field number for the "syntax" field.</summary>
     public const int SyntaxFieldNumber = 12;
-    private string syntax_ = "";
+    private readonly static string SyntaxDefaultValue = "";
+
+    private string syntax_;
     /// <summary>
     /// The syntax of the proto file.
     /// The supported values are "proto2" and "proto3".
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Syntax {
-      get { return syntax_; }
+      get { return syntax_ ?? SyntaxDefaultValue; }
       set {
         syntax_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "syntax" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasSyntax {
+      get { return syntax_ != null; }
+    }
+    /// <summary>Clears the value of the "syntax" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearSyntax() {
+      syntax_ = null;
+    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
@@ -547,8 +603,8 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
-      if (Package.Length != 0) hash ^= Package.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
+      if (HasPackage) hash ^= Package.GetHashCode();
       hash ^= dependency_.GetHashCode();
       hash ^= publicDependency_.GetHashCode();
       hash ^= weakDependency_.GetHashCode();
@@ -556,9 +612,9 @@
       hash ^= enumType_.GetHashCode();
       hash ^= service_.GetHashCode();
       hash ^= extension_.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
-      if (sourceCodeInfo_ != null) hash ^= SourceCodeInfo.GetHashCode();
-      if (Syntax.Length != 0) hash ^= Syntax.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
+      if (HasSourceCodeInfo) hash ^= SourceCodeInfo.GetHashCode();
+      if (HasSyntax) hash ^= Syntax.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -572,11 +628,11 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
-      if (Package.Length != 0) {
+      if (HasPackage) {
         output.WriteRawTag(18);
         output.WriteString(Package);
       }
@@ -585,17 +641,17 @@
       enumType_.WriteTo(output, _repeated_enumType_codec);
       service_.WriteTo(output, _repeated_service_codec);
       extension_.WriteTo(output, _repeated_extension_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(66);
         output.WriteMessage(Options);
       }
-      if (sourceCodeInfo_ != null) {
+      if (HasSourceCodeInfo) {
         output.WriteRawTag(74);
         output.WriteMessage(SourceCodeInfo);
       }
       publicDependency_.WriteTo(output, _repeated_publicDependency_codec);
       weakDependency_.WriteTo(output, _repeated_weakDependency_codec);
-      if (Syntax.Length != 0) {
+      if (HasSyntax) {
         output.WriteRawTag(98);
         output.WriteString(Syntax);
       }
@@ -607,10 +663,10 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
-      if (Package.Length != 0) {
+      if (HasPackage) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Package);
       }
       size += dependency_.CalculateSize(_repeated_dependency_codec);
@@ -620,13 +676,13 @@
       size += enumType_.CalculateSize(_repeated_enumType_codec);
       size += service_.CalculateSize(_repeated_service_codec);
       size += extension_.CalculateSize(_repeated_extension_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
-      if (sourceCodeInfo_ != null) {
+      if (HasSourceCodeInfo) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceCodeInfo);
       }
-      if (Syntax.Length != 0) {
+      if (HasSyntax) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Syntax);
       }
       if (_unknownFields != null) {
@@ -640,10 +696,10 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
-      if (other.Package.Length != 0) {
+      if (other.HasPackage) {
         Package = other.Package;
       }
       dependency_.Add(other.dependency_);
@@ -653,19 +709,19 @@
       enumType_.Add(other.enumType_);
       service_.Add(other.service_);
       extension_.Add(other.extension_);
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.FileOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.FileOptions();
         }
         Options.MergeFrom(other.Options);
       }
-      if (other.sourceCodeInfo_ != null) {
-        if (sourceCodeInfo_ == null) {
-          sourceCodeInfo_ = new global::Google.Protobuf.Reflection.SourceCodeInfo();
+      if (other.HasSourceCodeInfo) {
+        if (!HasSourceCodeInfo) {
+          SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo();
         }
         SourceCodeInfo.MergeFrom(other.SourceCodeInfo);
       }
-      if (other.Syntax.Length != 0) {
+      if (other.HasSyntax) {
         Syntax = other.Syntax;
       }
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -708,17 +764,17 @@
             break;
           }
           case 66: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.FileOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.FileOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
           case 74: {
-            if (sourceCodeInfo_ == null) {
-              sourceCodeInfo_ = new global::Google.Protobuf.Reflection.SourceCodeInfo();
+            if (!HasSourceCodeInfo) {
+              SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo();
             }
-            input.ReadMessage(sourceCodeInfo_);
+            input.ReadMessage(SourceCodeInfo);
             break;
           }
           case 82:
@@ -776,7 +832,7 @@
       enumType_ = other.enumType_.Clone();
       extensionRange_ = other.extensionRange_.Clone();
       oneofDecl_ = other.oneofDecl_.Clone();
-      options_ = other.options_ != null ? other.options_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
       reservedRange_ = other.reservedRange_.Clone();
       reservedName_ = other.reservedName_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -789,14 +845,26 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "field" field.</summary>
     public const int FieldFieldNumber = 2;
@@ -868,6 +936,16 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     /// <summary>Field number for the "reserved_range" field.</summary>
     public const int ReservedRangeFieldNumber = 9;
@@ -922,14 +1000,14 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
       hash ^= field_.GetHashCode();
       hash ^= extension_.GetHashCode();
       hash ^= nestedType_.GetHashCode();
       hash ^= enumType_.GetHashCode();
       hash ^= extensionRange_.GetHashCode();
       hash ^= oneofDecl_.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
       hash ^= reservedRange_.GetHashCode();
       hash ^= reservedName_.GetHashCode();
       if (_unknownFields != null) {
@@ -945,7 +1023,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
@@ -954,7 +1032,7 @@
       enumType_.WriteTo(output, _repeated_enumType_codec);
       extensionRange_.WriteTo(output, _repeated_extensionRange_codec);
       extension_.WriteTo(output, _repeated_extension_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(58);
         output.WriteMessage(Options);
       }
@@ -969,7 +1047,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
       size += field_.CalculateSize(_repeated_field_codec);
@@ -978,7 +1056,7 @@
       size += enumType_.CalculateSize(_repeated_enumType_codec);
       size += extensionRange_.CalculateSize(_repeated_extensionRange_codec);
       size += oneofDecl_.CalculateSize(_repeated_oneofDecl_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
@@ -994,7 +1072,7 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
       field_.Add(other.field_);
@@ -1003,9 +1081,9 @@
       enumType_.Add(other.enumType_);
       extensionRange_.Add(other.extensionRange_);
       oneofDecl_.Add(other.oneofDecl_);
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.MessageOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.MessageOptions();
         }
         Options.MergeFrom(other.Options);
       }
@@ -1047,10 +1125,10 @@
             break;
           }
           case 58: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.MessageOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.MessageOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
           case 66: {
@@ -1076,6 +1154,7 @@
       internal sealed partial class ExtensionRange : pb::IMessage<ExtensionRange> {
         private static readonly pb::MessageParser<ExtensionRange> _parser = new pb::MessageParser<ExtensionRange>(() => new ExtensionRange());
         private pb::UnknownFieldSet _unknownFields;
+        private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<ExtensionRange> Parser { get { return _parser; } }
 
@@ -1098,9 +1177,10 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public ExtensionRange(ExtensionRange other) : this() {
+          _hasBits0 = other._hasBits0;
           start_ = other.start_;
           end_ = other.end_;
-          options_ = other.options_ != null ? other.options_.Clone() : null;
+          options_ = other.HasOptions ? other.options_.Clone() : null;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
@@ -1111,25 +1191,51 @@
 
         /// <summary>Field number for the "start" field.</summary>
         public const int StartFieldNumber = 1;
+        private readonly static int StartDefaultValue = 0;
+
         private int start_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int Start {
-          get { return start_; }
+          get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } }
           set {
+            _hasBits0 |= 1;
             start_ = value;
           }
         }
+        /// <summary>Gets whether the "start" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasStart {
+          get { return (_hasBits0 & 1) != 0; }
+        }
+        /// <summary>Clears the value of the "start" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearStart() {
+          _hasBits0 &= ~1;
+        }
 
         /// <summary>Field number for the "end" field.</summary>
         public const int EndFieldNumber = 2;
+        private readonly static int EndDefaultValue = 0;
+
         private int end_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int End {
-          get { return end_; }
+          get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
+            _hasBits0 |= 2;
             end_ = value;
           }
         }
+        /// <summary>Gets whether the "end" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasEnd {
+          get { return (_hasBits0 & 2) != 0; }
+        }
+        /// <summary>Clears the value of the "end" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearEnd() {
+          _hasBits0 &= ~2;
+        }
 
         /// <summary>Field number for the "options" field.</summary>
         public const int OptionsFieldNumber = 3;
@@ -1141,6 +1247,16 @@
             options_ = value;
           }
         }
+        /// <summary>Gets whether the options field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasOptions {
+          get { return options_ != null; }
+        }
+        /// <summary>Clears the value of the options field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearOptions() {
+          options_ = null;
+        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override bool Equals(object other) {
@@ -1164,9 +1280,9 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override int GetHashCode() {
           int hash = 1;
-          if (Start != 0) hash ^= Start.GetHashCode();
-          if (End != 0) hash ^= End.GetHashCode();
-          if (options_ != null) hash ^= Options.GetHashCode();
+          if (HasStart) hash ^= Start.GetHashCode();
+          if (HasEnd) hash ^= End.GetHashCode();
+          if (HasOptions) hash ^= Options.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -1180,15 +1296,15 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (Start != 0) {
+          if (HasStart) {
             output.WriteRawTag(8);
             output.WriteInt32(Start);
           }
-          if (End != 0) {
+          if (HasEnd) {
             output.WriteRawTag(16);
             output.WriteInt32(End);
           }
-          if (options_ != null) {
+          if (HasOptions) {
             output.WriteRawTag(26);
             output.WriteMessage(Options);
           }
@@ -1200,13 +1316,13 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int CalculateSize() {
           int size = 0;
-          if (Start != 0) {
+          if (HasStart) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start);
           }
-          if (End != 0) {
+          if (HasEnd) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
           }
-          if (options_ != null) {
+          if (HasOptions) {
             size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
           }
           if (_unknownFields != null) {
@@ -1220,15 +1336,15 @@
           if (other == null) {
             return;
           }
-          if (other.Start != 0) {
+          if (other.HasStart) {
             Start = other.Start;
           }
-          if (other.End != 0) {
+          if (other.HasEnd) {
             End = other.End;
           }
-          if (other.options_ != null) {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
+          if (other.HasOptions) {
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
             }
             Options.MergeFrom(other.Options);
           }
@@ -1252,10 +1368,10 @@
                 break;
               }
               case 26: {
-                if (options_ == null) {
-                  options_ = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
+                if (!HasOptions) {
+                  Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
                 }
-                input.ReadMessage(options_);
+                input.ReadMessage(Options);
                 break;
               }
             }
@@ -1272,6 +1388,7 @@
       internal sealed partial class ReservedRange : pb::IMessage<ReservedRange> {
         private static readonly pb::MessageParser<ReservedRange> _parser = new pb::MessageParser<ReservedRange>(() => new ReservedRange());
         private pb::UnknownFieldSet _unknownFields;
+        private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<ReservedRange> Parser { get { return _parser; } }
 
@@ -1294,6 +1411,7 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public ReservedRange(ReservedRange other) : this() {
+          _hasBits0 = other._hasBits0;
           start_ = other.start_;
           end_ = other.end_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -1306,31 +1424,57 @@
 
         /// <summary>Field number for the "start" field.</summary>
         public const int StartFieldNumber = 1;
+        private readonly static int StartDefaultValue = 0;
+
         private int start_;
         /// <summary>
         /// Inclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int Start {
-          get { return start_; }
+          get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } }
           set {
+            _hasBits0 |= 1;
             start_ = value;
           }
         }
+        /// <summary>Gets whether the "start" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasStart {
+          get { return (_hasBits0 & 1) != 0; }
+        }
+        /// <summary>Clears the value of the "start" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearStart() {
+          _hasBits0 &= ~1;
+        }
 
         /// <summary>Field number for the "end" field.</summary>
         public const int EndFieldNumber = 2;
+        private readonly static int EndDefaultValue = 0;
+
         private int end_;
         /// <summary>
         /// Exclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int End {
-          get { return end_; }
+          get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
+            _hasBits0 |= 2;
             end_ = value;
           }
         }
+        /// <summary>Gets whether the "end" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasEnd {
+          get { return (_hasBits0 & 2) != 0; }
+        }
+        /// <summary>Clears the value of the "end" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearEnd() {
+          _hasBits0 &= ~2;
+        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override bool Equals(object other) {
@@ -1353,8 +1497,8 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override int GetHashCode() {
           int hash = 1;
-          if (Start != 0) hash ^= Start.GetHashCode();
-          if (End != 0) hash ^= End.GetHashCode();
+          if (HasStart) hash ^= Start.GetHashCode();
+          if (HasEnd) hash ^= End.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -1368,11 +1512,11 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (Start != 0) {
+          if (HasStart) {
             output.WriteRawTag(8);
             output.WriteInt32(Start);
           }
-          if (End != 0) {
+          if (HasEnd) {
             output.WriteRawTag(16);
             output.WriteInt32(End);
           }
@@ -1384,10 +1528,10 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int CalculateSize() {
           int size = 0;
-          if (Start != 0) {
+          if (HasStart) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start);
           }
-          if (End != 0) {
+          if (HasEnd) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
           }
           if (_unknownFields != null) {
@@ -1401,10 +1545,10 @@
           if (other == null) {
             return;
           }
-          if (other.Start != 0) {
+          if (other.HasStart) {
             Start = other.Start;
           }
-          if (other.End != 0) {
+          if (other.HasEnd) {
             End = other.End;
           }
           _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -1567,6 +1711,7 @@
   internal sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto> {
     private static readonly pb::MessageParser<FieldDescriptorProto> _parser = new pb::MessageParser<FieldDescriptorProto>(() => new FieldDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FieldDescriptorProto> Parser { get { return _parser; } }
 
@@ -1589,6 +1734,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FieldDescriptorProto(FieldDescriptorProto other) : this() {
+      _hasBits0 = other._hasBits0;
       name_ = other.name_;
       number_ = other.number_;
       label_ = other.label_;
@@ -1598,7 +1744,7 @@
       defaultValue_ = other.defaultValue_;
       oneofIndex_ = other.oneofIndex_;
       jsonName_ = other.jsonName_;
-      options_ = other.options_ != null ? other.options_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
@@ -1609,55 +1755,108 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "number" field.</summary>
     public const int NumberFieldNumber = 3;
+    private readonly static int NumberDefaultValue = 0;
+
     private int number_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int Number {
-      get { return number_; }
+      get { if ((_hasBits0 & 1) != 0) { return number_; } else { return NumberDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         number_ = value;
       }
     }
+    /// <summary>Gets whether the "number" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasNumber {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "number" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearNumber() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "label" field.</summary>
     public const int LabelFieldNumber = 4;
-    private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_ = 0;
+    private readonly static global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label LabelDefaultValue = global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label.Optional;
+
+    private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label label_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label Label {
-      get { return label_; }
+      get { if ((_hasBits0 & 2) != 0) { return label_; } else { return LabelDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         label_ = value;
       }
     }
+    /// <summary>Gets whether the "label" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasLabel {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "label" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearLabel() {
+      _hasBits0 &= ~2;
+    }
 
     /// <summary>Field number for the "type" field.</summary>
     public const int TypeFieldNumber = 5;
-    private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type type_ = 0;
+    private readonly static global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type TypeDefaultValue = global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type.Double;
+
+    private global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type type_;
     /// <summary>
     /// If type_name is set, this need not be set.  If both this and type_name
     /// are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type Type {
-      get { return type_; }
+      get { if ((_hasBits0 & 4) != 0) { return type_; } else { return TypeDefaultValue; } }
       set {
+        _hasBits0 |= 4;
         type_ = value;
       }
     }
+    /// <summary>Gets whether the "type" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasType {
+      get { return (_hasBits0 & 4) != 0; }
+    }
+    /// <summary>Clears the value of the "type" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearType() {
+      _hasBits0 &= ~4;
+    }
 
     /// <summary>Field number for the "type_name" field.</summary>
     public const int TypeNameFieldNumber = 6;
-    private string typeName_ = "";
+    private readonly static string TypeNameDefaultValue = "";
+
+    private string typeName_;
     /// <summary>
     /// For message and enum types, this is the name of the type.  If the name
     /// starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
@@ -1667,30 +1866,54 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string TypeName {
-      get { return typeName_; }
+      get { return typeName_ ?? TypeNameDefaultValue; }
       set {
         typeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "type_name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasTypeName {
+      get { return typeName_ != null; }
+    }
+    /// <summary>Clears the value of the "type_name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearTypeName() {
+      typeName_ = null;
+    }
 
     /// <summary>Field number for the "extendee" field.</summary>
     public const int ExtendeeFieldNumber = 2;
-    private string extendee_ = "";
+    private readonly static string ExtendeeDefaultValue = "";
+
+    private string extendee_;
     /// <summary>
     /// For extensions, this is the name of the type being extended.  It is
     /// resolved in the same manner as type_name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Extendee {
-      get { return extendee_; }
+      get { return extendee_ ?? ExtendeeDefaultValue; }
       set {
         extendee_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "extendee" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasExtendee {
+      get { return extendee_ != null; }
+    }
+    /// <summary>Clears the value of the "extendee" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearExtendee() {
+      extendee_ = null;
+    }
 
     /// <summary>Field number for the "default_value" field.</summary>
     public const int DefaultValueFieldNumber = 7;
-    private string defaultValue_ = "";
+    private readonly static string DefaultValueDefaultValue = "";
+
+    private string defaultValue_;
     /// <summary>
     /// For numeric types, contains the original text representation of the value.
     /// For booleans, "true" or "false".
@@ -1700,14 +1923,26 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string DefaultValue {
-      get { return defaultValue_; }
+      get { return defaultValue_ ?? DefaultValueDefaultValue; }
       set {
         defaultValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "default_value" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDefaultValue {
+      get { return defaultValue_ != null; }
+    }
+    /// <summary>Clears the value of the "default_value" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDefaultValue() {
+      defaultValue_ = null;
+    }
 
     /// <summary>Field number for the "oneof_index" field.</summary>
     public const int OneofIndexFieldNumber = 9;
+    private readonly static int OneofIndexDefaultValue = 0;
+
     private int oneofIndex_;
     /// <summary>
     /// If set, gives the index of a oneof in the containing type's oneof_decl
@@ -1715,15 +1950,28 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int OneofIndex {
-      get { return oneofIndex_; }
+      get { if ((_hasBits0 & 8) != 0) { return oneofIndex_; } else { return OneofIndexDefaultValue; } }
       set {
+        _hasBits0 |= 8;
         oneofIndex_ = value;
       }
     }
+    /// <summary>Gets whether the "oneof_index" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOneofIndex {
+      get { return (_hasBits0 & 8) != 0; }
+    }
+    /// <summary>Clears the value of the "oneof_index" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOneofIndex() {
+      _hasBits0 &= ~8;
+    }
 
     /// <summary>Field number for the "json_name" field.</summary>
     public const int JsonNameFieldNumber = 10;
-    private string jsonName_ = "";
+    private readonly static string JsonNameDefaultValue = "";
+
+    private string jsonName_;
     /// <summary>
     /// JSON name of this field. The value is set by protocol compiler. If the
     /// user has set a "json_name" option on this field, that option's value
@@ -1732,11 +1980,21 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string JsonName {
-      get { return jsonName_; }
+      get { return jsonName_ ?? JsonNameDefaultValue; }
       set {
         jsonName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "json_name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJsonName {
+      get { return jsonName_ != null; }
+    }
+    /// <summary>Clears the value of the "json_name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJsonName() {
+      jsonName_ = null;
+    }
 
     /// <summary>Field number for the "options" field.</summary>
     public const int OptionsFieldNumber = 8;
@@ -1748,6 +2006,16 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
@@ -1778,16 +2046,16 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
-      if (Number != 0) hash ^= Number.GetHashCode();
-      if (Label != 0) hash ^= Label.GetHashCode();
-      if (Type != 0) hash ^= Type.GetHashCode();
-      if (TypeName.Length != 0) hash ^= TypeName.GetHashCode();
-      if (Extendee.Length != 0) hash ^= Extendee.GetHashCode();
-      if (DefaultValue.Length != 0) hash ^= DefaultValue.GetHashCode();
-      if (OneofIndex != 0) hash ^= OneofIndex.GetHashCode();
-      if (JsonName.Length != 0) hash ^= JsonName.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
+      if (HasNumber) hash ^= Number.GetHashCode();
+      if (HasLabel) hash ^= Label.GetHashCode();
+      if (HasType) hash ^= Type.GetHashCode();
+      if (HasTypeName) hash ^= TypeName.GetHashCode();
+      if (HasExtendee) hash ^= Extendee.GetHashCode();
+      if (HasDefaultValue) hash ^= DefaultValue.GetHashCode();
+      if (HasOneofIndex) hash ^= OneofIndex.GetHashCode();
+      if (HasJsonName) hash ^= JsonName.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -1801,43 +2069,43 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
-      if (Extendee.Length != 0) {
+      if (HasExtendee) {
         output.WriteRawTag(18);
         output.WriteString(Extendee);
       }
-      if (Number != 0) {
+      if (HasNumber) {
         output.WriteRawTag(24);
         output.WriteInt32(Number);
       }
-      if (Label != 0) {
+      if (HasLabel) {
         output.WriteRawTag(32);
         output.WriteEnum((int) Label);
       }
-      if (Type != 0) {
+      if (HasType) {
         output.WriteRawTag(40);
         output.WriteEnum((int) Type);
       }
-      if (TypeName.Length != 0) {
+      if (HasTypeName) {
         output.WriteRawTag(50);
         output.WriteString(TypeName);
       }
-      if (DefaultValue.Length != 0) {
+      if (HasDefaultValue) {
         output.WriteRawTag(58);
         output.WriteString(DefaultValue);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(66);
         output.WriteMessage(Options);
       }
-      if (OneofIndex != 0) {
+      if (HasOneofIndex) {
         output.WriteRawTag(72);
         output.WriteInt32(OneofIndex);
       }
-      if (JsonName.Length != 0) {
+      if (HasJsonName) {
         output.WriteRawTag(82);
         output.WriteString(JsonName);
       }
@@ -1849,34 +2117,34 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
-      if (Number != 0) {
+      if (HasNumber) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
       }
-      if (Label != 0) {
+      if (HasLabel) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Label);
       }
-      if (Type != 0) {
+      if (HasType) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
       }
-      if (TypeName.Length != 0) {
+      if (HasTypeName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(TypeName);
       }
-      if (Extendee.Length != 0) {
+      if (HasExtendee) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Extendee);
       }
-      if (DefaultValue.Length != 0) {
+      if (HasDefaultValue) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(DefaultValue);
       }
-      if (OneofIndex != 0) {
+      if (HasOneofIndex) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofIndex);
       }
-      if (JsonName.Length != 0) {
+      if (HasJsonName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (_unknownFields != null) {
@@ -1890,36 +2158,36 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
-      if (other.Number != 0) {
+      if (other.HasNumber) {
         Number = other.Number;
       }
-      if (other.Label != 0) {
+      if (other.HasLabel) {
         Label = other.Label;
       }
-      if (other.Type != 0) {
+      if (other.HasType) {
         Type = other.Type;
       }
-      if (other.TypeName.Length != 0) {
+      if (other.HasTypeName) {
         TypeName = other.TypeName;
       }
-      if (other.Extendee.Length != 0) {
+      if (other.HasExtendee) {
         Extendee = other.Extendee;
       }
-      if (other.DefaultValue.Length != 0) {
+      if (other.HasDefaultValue) {
         DefaultValue = other.DefaultValue;
       }
-      if (other.OneofIndex != 0) {
+      if (other.HasOneofIndex) {
         OneofIndex = other.OneofIndex;
       }
-      if (other.JsonName.Length != 0) {
+      if (other.HasJsonName) {
         JsonName = other.JsonName;
       }
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.FieldOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.FieldOptions();
         }
         Options.MergeFrom(other.Options);
       }
@@ -1947,11 +2215,11 @@
             break;
           }
           case 32: {
-            label_ = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) input.ReadEnum();
+            Label = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) input.ReadEnum();
             break;
           }
           case 40: {
-            type_ = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type) input.ReadEnum();
+            Type = (global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type) input.ReadEnum();
             break;
           }
           case 50: {
@@ -1963,10 +2231,10 @@
             break;
           }
           case 66: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.FieldOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.FieldOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
           case 72: {
@@ -2079,7 +2347,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public OneofDescriptorProto(OneofDescriptorProto other) : this() {
       name_ = other.name_;
-      options_ = other.options_ != null ? other.options_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
@@ -2090,14 +2358,26 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "options" field.</summary>
     public const int OptionsFieldNumber = 2;
@@ -2109,6 +2389,16 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
@@ -2131,8 +2421,8 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -2146,11 +2436,11 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(18);
         output.WriteMessage(Options);
       }
@@ -2162,10 +2452,10 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (_unknownFields != null) {
@@ -2179,12 +2469,12 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.OneofOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.OneofOptions();
         }
         Options.MergeFrom(other.Options);
       }
@@ -2204,10 +2494,10 @@
             break;
           }
           case 18: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.OneofOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.OneofOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
         }
@@ -2246,7 +2536,7 @@
     public EnumDescriptorProto(EnumDescriptorProto other) : this() {
       name_ = other.name_;
       value_ = other.value_.Clone();
-      options_ = other.options_ != null ? other.options_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
       reservedRange_ = other.reservedRange_.Clone();
       reservedName_ = other.reservedName_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -2259,14 +2549,26 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "value" field.</summary>
     public const int ValueFieldNumber = 2;
@@ -2288,6 +2590,16 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     /// <summary>Field number for the "reserved_range" field.</summary>
     public const int ReservedRangeFieldNumber = 4;
@@ -2342,9 +2654,9 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
       hash ^= value_.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
       hash ^= reservedRange_.GetHashCode();
       hash ^= reservedName_.GetHashCode();
       if (_unknownFields != null) {
@@ -2360,12 +2672,12 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
       value_.WriteTo(output, _repeated_value_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(26);
         output.WriteMessage(Options);
       }
@@ -2379,11 +2691,11 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
       size += value_.CalculateSize(_repeated_value_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
@@ -2399,13 +2711,13 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
       value_.Add(other.value_);
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.EnumOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.EnumOptions();
         }
         Options.MergeFrom(other.Options);
       }
@@ -2431,10 +2743,10 @@
             break;
           }
           case 26: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.EnumOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.EnumOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
           case 34: {
@@ -2464,6 +2776,7 @@
       internal sealed partial class EnumReservedRange : pb::IMessage<EnumReservedRange> {
         private static readonly pb::MessageParser<EnumReservedRange> _parser = new pb::MessageParser<EnumReservedRange>(() => new EnumReservedRange());
         private pb::UnknownFieldSet _unknownFields;
+        private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<EnumReservedRange> Parser { get { return _parser; } }
 
@@ -2486,6 +2799,7 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public EnumReservedRange(EnumReservedRange other) : this() {
+          _hasBits0 = other._hasBits0;
           start_ = other.start_;
           end_ = other.end_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -2498,31 +2812,57 @@
 
         /// <summary>Field number for the "start" field.</summary>
         public const int StartFieldNumber = 1;
+        private readonly static int StartDefaultValue = 0;
+
         private int start_;
         /// <summary>
         /// Inclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int Start {
-          get { return start_; }
+          get { if ((_hasBits0 & 1) != 0) { return start_; } else { return StartDefaultValue; } }
           set {
+            _hasBits0 |= 1;
             start_ = value;
           }
         }
+        /// <summary>Gets whether the "start" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasStart {
+          get { return (_hasBits0 & 1) != 0; }
+        }
+        /// <summary>Clears the value of the "start" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearStart() {
+          _hasBits0 &= ~1;
+        }
 
         /// <summary>Field number for the "end" field.</summary>
         public const int EndFieldNumber = 2;
+        private readonly static int EndDefaultValue = 0;
+
         private int end_;
         /// <summary>
         /// Inclusive.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int End {
-          get { return end_; }
+          get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
+            _hasBits0 |= 2;
             end_ = value;
           }
         }
+        /// <summary>Gets whether the "end" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasEnd {
+          get { return (_hasBits0 & 2) != 0; }
+        }
+        /// <summary>Clears the value of the "end" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearEnd() {
+          _hasBits0 &= ~2;
+        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override bool Equals(object other) {
@@ -2545,8 +2885,8 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override int GetHashCode() {
           int hash = 1;
-          if (Start != 0) hash ^= Start.GetHashCode();
-          if (End != 0) hash ^= End.GetHashCode();
+          if (HasStart) hash ^= Start.GetHashCode();
+          if (HasEnd) hash ^= End.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -2560,11 +2900,11 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (Start != 0) {
+          if (HasStart) {
             output.WriteRawTag(8);
             output.WriteInt32(Start);
           }
-          if (End != 0) {
+          if (HasEnd) {
             output.WriteRawTag(16);
             output.WriteInt32(End);
           }
@@ -2576,10 +2916,10 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int CalculateSize() {
           int size = 0;
-          if (Start != 0) {
+          if (HasStart) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(Start);
           }
-          if (End != 0) {
+          if (HasEnd) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
           }
           if (_unknownFields != null) {
@@ -2593,10 +2933,10 @@
           if (other == null) {
             return;
           }
-          if (other.Start != 0) {
+          if (other.HasStart) {
             Start = other.Start;
           }
-          if (other.End != 0) {
+          if (other.HasEnd) {
             End = other.End;
           }
           _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -2635,6 +2975,7 @@
   internal sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto> {
     private static readonly pb::MessageParser<EnumValueDescriptorProto> _parser = new pb::MessageParser<EnumValueDescriptorProto>(() => new EnumValueDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EnumValueDescriptorProto> Parser { get { return _parser; } }
 
@@ -2657,9 +2998,10 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public EnumValueDescriptorProto(EnumValueDescriptorProto other) : this() {
+      _hasBits0 = other._hasBits0;
       name_ = other.name_;
       number_ = other.number_;
-      options_ = other.options_ != null ? other.options_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
@@ -2670,25 +3012,50 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "number" field.</summary>
     public const int NumberFieldNumber = 2;
+    private readonly static int NumberDefaultValue = 0;
+
     private int number_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int Number {
-      get { return number_; }
+      get { if ((_hasBits0 & 1) != 0) { return number_; } else { return NumberDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         number_ = value;
       }
     }
+    /// <summary>Gets whether the "number" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasNumber {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "number" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearNumber() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "options" field.</summary>
     public const int OptionsFieldNumber = 3;
@@ -2700,6 +3067,16 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
@@ -2723,9 +3100,9 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
-      if (Number != 0) hash ^= Number.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
+      if (HasNumber) hash ^= Number.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -2739,15 +3116,15 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
-      if (Number != 0) {
+      if (HasNumber) {
         output.WriteRawTag(16);
         output.WriteInt32(Number);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(26);
         output.WriteMessage(Options);
       }
@@ -2759,13 +3136,13 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
-      if (Number != 0) {
+      if (HasNumber) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (_unknownFields != null) {
@@ -2779,15 +3156,15 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
-      if (other.Number != 0) {
+      if (other.HasNumber) {
         Number = other.Number;
       }
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.EnumValueOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.EnumValueOptions();
         }
         Options.MergeFrom(other.Options);
       }
@@ -2811,10 +3188,10 @@
             break;
           }
           case 26: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.EnumValueOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.EnumValueOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
         }
@@ -2853,7 +3230,7 @@
     public ServiceDescriptorProto(ServiceDescriptorProto other) : this() {
       name_ = other.name_;
       method_ = other.method_.Clone();
-      options_ = other.options_ != null ? other.options_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
@@ -2864,14 +3241,26 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "method" field.</summary>
     public const int MethodFieldNumber = 2;
@@ -2893,6 +3282,16 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
@@ -2916,9 +3315,9 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
       hash ^= method_.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -2932,12 +3331,12 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
       method_.WriteTo(output, _repeated_method_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(26);
         output.WriteMessage(Options);
       }
@@ -2949,11 +3348,11 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
       size += method_.CalculateSize(_repeated_method_codec);
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
       if (_unknownFields != null) {
@@ -2967,13 +3366,13 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
       method_.Add(other.method_);
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.ServiceOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.ServiceOptions();
         }
         Options.MergeFrom(other.Options);
       }
@@ -2997,10 +3396,10 @@
             break;
           }
           case 26: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.ServiceOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.ServiceOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
         }
@@ -3015,6 +3414,7 @@
   internal sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto> {
     private static readonly pb::MessageParser<MethodDescriptorProto> _parser = new pb::MessageParser<MethodDescriptorProto>(() => new MethodDescriptorProto());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MethodDescriptorProto> Parser { get { return _parser; } }
 
@@ -3037,10 +3437,11 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public MethodDescriptorProto(MethodDescriptorProto other) : this() {
+      _hasBits0 = other._hasBits0;
       name_ = other.name_;
       inputType_ = other.inputType_;
       outputType_ = other.outputType_;
-      options_ = other.options_ != null ? other.options_.Clone() : null;
+      options_ = other.HasOptions ? other.options_.Clone() : null;
       clientStreaming_ = other.clientStreaming_;
       serverStreaming_ = other.serverStreaming_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -3053,40 +3454,76 @@
 
     /// <summary>Field number for the "name" field.</summary>
     public const int NameFieldNumber = 1;
-    private string name_ = "";
+    private readonly static string NameDefaultValue = "";
+
+    private string name_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
-      get { return name_; }
+      get { return name_ ?? NameDefaultValue; }
       set {
         name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "name" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasName {
+      get { return name_ != null; }
+    }
+    /// <summary>Clears the value of the "name" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearName() {
+      name_ = null;
+    }
 
     /// <summary>Field number for the "input_type" field.</summary>
     public const int InputTypeFieldNumber = 2;
-    private string inputType_ = "";
+    private readonly static string InputTypeDefaultValue = "";
+
+    private string inputType_;
     /// <summary>
     /// Input and output type names.  These are resolved in the same way as
     /// FieldDescriptorProto.type_name, but must refer to a message type.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string InputType {
-      get { return inputType_; }
+      get { return inputType_ ?? InputTypeDefaultValue; }
       set {
         inputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "input_type" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasInputType {
+      get { return inputType_ != null; }
+    }
+    /// <summary>Clears the value of the "input_type" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearInputType() {
+      inputType_ = null;
+    }
 
     /// <summary>Field number for the "output_type" field.</summary>
     public const int OutputTypeFieldNumber = 3;
-    private string outputType_ = "";
+    private readonly static string OutputTypeDefaultValue = "";
+
+    private string outputType_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string OutputType {
-      get { return outputType_; }
+      get { return outputType_ ?? OutputTypeDefaultValue; }
       set {
         outputType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "output_type" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOutputType {
+      get { return outputType_ != null; }
+    }
+    /// <summary>Clears the value of the "output_type" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOutputType() {
+      outputType_ = null;
+    }
 
     /// <summary>Field number for the "options" field.</summary>
     public const int OptionsFieldNumber = 4;
@@ -3098,34 +3535,70 @@
         options_ = value;
       }
     }
+    /// <summary>Gets whether the options field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptions {
+      get { return options_ != null; }
+    }
+    /// <summary>Clears the value of the options field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptions() {
+      options_ = null;
+    }
 
     /// <summary>Field number for the "client_streaming" field.</summary>
     public const int ClientStreamingFieldNumber = 5;
+    private readonly static bool ClientStreamingDefaultValue = false;
+
     private bool clientStreaming_;
     /// <summary>
     /// Identifies if client streams multiple client messages
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool ClientStreaming {
-      get { return clientStreaming_; }
+      get { if ((_hasBits0 & 1) != 0) { return clientStreaming_; } else { return ClientStreamingDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         clientStreaming_ = value;
       }
     }
+    /// <summary>Gets whether the "client_streaming" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasClientStreaming {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "client_streaming" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearClientStreaming() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "server_streaming" field.</summary>
     public const int ServerStreamingFieldNumber = 6;
+    private readonly static bool ServerStreamingDefaultValue = false;
+
     private bool serverStreaming_;
     /// <summary>
     /// Identifies if server streams multiple server messages
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool ServerStreaming {
-      get { return serverStreaming_; }
+      get { if ((_hasBits0 & 2) != 0) { return serverStreaming_; } else { return ServerStreamingDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         serverStreaming_ = value;
       }
     }
+    /// <summary>Gets whether the "server_streaming" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasServerStreaming {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "server_streaming" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearServerStreaming() {
+      _hasBits0 &= ~2;
+    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
@@ -3152,12 +3625,12 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Name.Length != 0) hash ^= Name.GetHashCode();
-      if (InputType.Length != 0) hash ^= InputType.GetHashCode();
-      if (OutputType.Length != 0) hash ^= OutputType.GetHashCode();
-      if (options_ != null) hash ^= Options.GetHashCode();
-      if (ClientStreaming != false) hash ^= ClientStreaming.GetHashCode();
-      if (ServerStreaming != false) hash ^= ServerStreaming.GetHashCode();
+      if (HasName) hash ^= Name.GetHashCode();
+      if (HasInputType) hash ^= InputType.GetHashCode();
+      if (HasOutputType) hash ^= OutputType.GetHashCode();
+      if (HasOptions) hash ^= Options.GetHashCode();
+      if (HasClientStreaming) hash ^= ClientStreaming.GetHashCode();
+      if (HasServerStreaming) hash ^= ServerStreaming.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -3171,27 +3644,27 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Name.Length != 0) {
+      if (HasName) {
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
-      if (InputType.Length != 0) {
+      if (HasInputType) {
         output.WriteRawTag(18);
         output.WriteString(InputType);
       }
-      if (OutputType.Length != 0) {
+      if (HasOutputType) {
         output.WriteRawTag(26);
         output.WriteString(OutputType);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         output.WriteRawTag(34);
         output.WriteMessage(Options);
       }
-      if (ClientStreaming != false) {
+      if (HasClientStreaming) {
         output.WriteRawTag(40);
         output.WriteBool(ClientStreaming);
       }
-      if (ServerStreaming != false) {
+      if (HasServerStreaming) {
         output.WriteRawTag(48);
         output.WriteBool(ServerStreaming);
       }
@@ -3203,22 +3676,22 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Name.Length != 0) {
+      if (HasName) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
-      if (InputType.Length != 0) {
+      if (HasInputType) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(InputType);
       }
-      if (OutputType.Length != 0) {
+      if (HasOutputType) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(OutputType);
       }
-      if (options_ != null) {
+      if (HasOptions) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
       }
-      if (ClientStreaming != false) {
+      if (HasClientStreaming) {
         size += 1 + 1;
       }
-      if (ServerStreaming != false) {
+      if (HasServerStreaming) {
         size += 1 + 1;
       }
       if (_unknownFields != null) {
@@ -3232,25 +3705,25 @@
       if (other == null) {
         return;
       }
-      if (other.Name.Length != 0) {
+      if (other.HasName) {
         Name = other.Name;
       }
-      if (other.InputType.Length != 0) {
+      if (other.HasInputType) {
         InputType = other.InputType;
       }
-      if (other.OutputType.Length != 0) {
+      if (other.HasOutputType) {
         OutputType = other.OutputType;
       }
-      if (other.options_ != null) {
-        if (options_ == null) {
-          options_ = new global::Google.Protobuf.Reflection.MethodOptions();
+      if (other.HasOptions) {
+        if (!HasOptions) {
+          Options = new global::Google.Protobuf.Reflection.MethodOptions();
         }
         Options.MergeFrom(other.Options);
       }
-      if (other.ClientStreaming != false) {
+      if (other.HasClientStreaming) {
         ClientStreaming = other.ClientStreaming;
       }
-      if (other.ServerStreaming != false) {
+      if (other.HasServerStreaming) {
         ServerStreaming = other.ServerStreaming;
       }
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -3277,10 +3750,10 @@
             break;
           }
           case 34: {
-            if (options_ == null) {
-              options_ = new global::Google.Protobuf.Reflection.MethodOptions();
+            if (!HasOptions) {
+              Options = new global::Google.Protobuf.Reflection.MethodOptions();
             }
-            input.ReadMessage(options_);
+            input.ReadMessage(Options);
             break;
           }
           case 40: {
@@ -3300,6 +3773,7 @@
   internal sealed partial class FileOptions : pb::IMessage<FileOptions> {
     private static readonly pb::MessageParser<FileOptions> _parser = new pb::MessageParser<FileOptions>(() => new FileOptions());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FileOptions> Parser { get { return _parser; } }
 
@@ -3324,6 +3798,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FileOptions(FileOptions other) : this() {
+      _hasBits0 = other._hasBits0;
       javaPackage_ = other.javaPackage_;
       javaOuterClassname_ = other.javaOuterClassname_;
       javaMultipleFiles_ = other.javaMultipleFiles_;
@@ -3355,7 +3830,9 @@
 
     /// <summary>Field number for the "java_package" field.</summary>
     public const int JavaPackageFieldNumber = 1;
-    private string javaPackage_ = "";
+    private readonly static string JavaPackageDefaultValue = "";
+
+    private string javaPackage_;
     /// <summary>
     /// Sets the Java package where classes generated from this .proto will be
     /// placed.  By default, the proto package is used, but this is often
@@ -3364,15 +3841,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string JavaPackage {
-      get { return javaPackage_; }
+      get { return javaPackage_ ?? JavaPackageDefaultValue; }
       set {
         javaPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "java_package" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJavaPackage {
+      get { return javaPackage_ != null; }
+    }
+    /// <summary>Clears the value of the "java_package" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJavaPackage() {
+      javaPackage_ = null;
+    }
 
     /// <summary>Field number for the "java_outer_classname" field.</summary>
     public const int JavaOuterClassnameFieldNumber = 8;
-    private string javaOuterClassname_ = "";
+    private readonly static string JavaOuterClassnameDefaultValue = "";
+
+    private string javaOuterClassname_;
     /// <summary>
     /// If set, all the classes from the .proto file are wrapped in a single
     /// outer class with the given name.  This applies to both Proto1
@@ -3382,14 +3871,26 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string JavaOuterClassname {
-      get { return javaOuterClassname_; }
+      get { return javaOuterClassname_ ?? JavaOuterClassnameDefaultValue; }
       set {
         javaOuterClassname_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "java_outer_classname" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJavaOuterClassname {
+      get { return javaOuterClassname_ != null; }
+    }
+    /// <summary>Clears the value of the "java_outer_classname" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJavaOuterClassname() {
+      javaOuterClassname_ = null;
+    }
 
     /// <summary>Field number for the "java_multiple_files" field.</summary>
     public const int JavaMultipleFilesFieldNumber = 10;
+    private readonly static bool JavaMultipleFilesDefaultValue = false;
+
     private bool javaMultipleFiles_;
     /// <summary>
     /// If set true, then the Java code generator will generate a separate .java
@@ -3401,14 +3902,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool JavaMultipleFiles {
-      get { return javaMultipleFiles_; }
+      get { if ((_hasBits0 & 2) != 0) { return javaMultipleFiles_; } else { return JavaMultipleFilesDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         javaMultipleFiles_ = value;
       }
     }
+    /// <summary>Gets whether the "java_multiple_files" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJavaMultipleFiles {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "java_multiple_files" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJavaMultipleFiles() {
+      _hasBits0 &= ~2;
+    }
 
     /// <summary>Field number for the "java_generate_equals_and_hash" field.</summary>
     public const int JavaGenerateEqualsAndHashFieldNumber = 20;
+    private readonly static bool JavaGenerateEqualsAndHashDefaultValue = false;
+
     private bool javaGenerateEqualsAndHash_;
     /// <summary>
     /// This option does nothing.
@@ -3416,14 +3930,29 @@
     [global::System.ObsoleteAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool JavaGenerateEqualsAndHash {
-      get { return javaGenerateEqualsAndHash_; }
+      get { if ((_hasBits0 & 32) != 0) { return javaGenerateEqualsAndHash_; } else { return JavaGenerateEqualsAndHashDefaultValue; } }
       set {
+        _hasBits0 |= 32;
         javaGenerateEqualsAndHash_ = value;
       }
     }
+    /// <summary>Gets whether the "java_generate_equals_and_hash" field is set</summary>
+    [global::System.ObsoleteAttribute]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJavaGenerateEqualsAndHash {
+      get { return (_hasBits0 & 32) != 0; }
+    }
+    /// <summary>Clears the value of the "java_generate_equals_and_hash" field</summary>
+    [global::System.ObsoleteAttribute]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJavaGenerateEqualsAndHash() {
+      _hasBits0 &= ~32;
+    }
 
     /// <summary>Field number for the "java_string_check_utf8" field.</summary>
     public const int JavaStringCheckUtf8FieldNumber = 27;
+    private readonly static bool JavaStringCheckUtf8DefaultValue = false;
+
     private bool javaStringCheckUtf8_;
     /// <summary>
     /// If set true, then the Java2 code generator will generate code that
@@ -3435,26 +3964,52 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool JavaStringCheckUtf8 {
-      get { return javaStringCheckUtf8_; }
+      get { if ((_hasBits0 & 128) != 0) { return javaStringCheckUtf8_; } else { return JavaStringCheckUtf8DefaultValue; } }
       set {
+        _hasBits0 |= 128;
         javaStringCheckUtf8_ = value;
       }
     }
+    /// <summary>Gets whether the "java_string_check_utf8" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJavaStringCheckUtf8 {
+      get { return (_hasBits0 & 128) != 0; }
+    }
+    /// <summary>Clears the value of the "java_string_check_utf8" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJavaStringCheckUtf8() {
+      _hasBits0 &= ~128;
+    }
 
     /// <summary>Field number for the "optimize_for" field.</summary>
     public const int OptimizeForFieldNumber = 9;
-    private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_ = 0;
+    private readonly static global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode OptimizeForDefaultValue = global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode.Speed;
+
+    private global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode optimizeFor_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode OptimizeFor {
-      get { return optimizeFor_; }
+      get { if ((_hasBits0 & 1) != 0) { return optimizeFor_; } else { return OptimizeForDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         optimizeFor_ = value;
       }
     }
+    /// <summary>Gets whether the "optimize_for" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasOptimizeFor {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "optimize_for" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearOptimizeFor() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "go_package" field.</summary>
     public const int GoPackageFieldNumber = 11;
-    private string goPackage_ = "";
+    private readonly static string GoPackageDefaultValue = "";
+
+    private string goPackage_;
     /// <summary>
     /// Sets the Go package where structs generated from this .proto will be
     /// placed. If omitted, the Go package will be derived from the following:
@@ -3464,14 +4019,26 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string GoPackage {
-      get { return goPackage_; }
+      get { return goPackage_ ?? GoPackageDefaultValue; }
       set {
         goPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "go_package" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasGoPackage {
+      get { return goPackage_ != null; }
+    }
+    /// <summary>Clears the value of the "go_package" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearGoPackage() {
+      goPackage_ = null;
+    }
 
     /// <summary>Field number for the "cc_generic_services" field.</summary>
     public const int CcGenericServicesFieldNumber = 16;
+    private readonly static bool CcGenericServicesDefaultValue = false;
+
     private bool ccGenericServices_;
     /// <summary>
     /// Should generic services be generated in each language?  "Generic" services
@@ -3487,47 +4054,99 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool CcGenericServices {
-      get { return ccGenericServices_; }
+      get { if ((_hasBits0 & 4) != 0) { return ccGenericServices_; } else { return CcGenericServicesDefaultValue; } }
       set {
+        _hasBits0 |= 4;
         ccGenericServices_ = value;
       }
     }
+    /// <summary>Gets whether the "cc_generic_services" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasCcGenericServices {
+      get { return (_hasBits0 & 4) != 0; }
+    }
+    /// <summary>Clears the value of the "cc_generic_services" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearCcGenericServices() {
+      _hasBits0 &= ~4;
+    }
 
     /// <summary>Field number for the "java_generic_services" field.</summary>
     public const int JavaGenericServicesFieldNumber = 17;
+    private readonly static bool JavaGenericServicesDefaultValue = false;
+
     private bool javaGenericServices_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool JavaGenericServices {
-      get { return javaGenericServices_; }
+      get { if ((_hasBits0 & 8) != 0) { return javaGenericServices_; } else { return JavaGenericServicesDefaultValue; } }
       set {
+        _hasBits0 |= 8;
         javaGenericServices_ = value;
       }
     }
+    /// <summary>Gets whether the "java_generic_services" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJavaGenericServices {
+      get { return (_hasBits0 & 8) != 0; }
+    }
+    /// <summary>Clears the value of the "java_generic_services" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJavaGenericServices() {
+      _hasBits0 &= ~8;
+    }
 
     /// <summary>Field number for the "py_generic_services" field.</summary>
     public const int PyGenericServicesFieldNumber = 18;
+    private readonly static bool PyGenericServicesDefaultValue = false;
+
     private bool pyGenericServices_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool PyGenericServices {
-      get { return pyGenericServices_; }
+      get { if ((_hasBits0 & 16) != 0) { return pyGenericServices_; } else { return PyGenericServicesDefaultValue; } }
       set {
+        _hasBits0 |= 16;
         pyGenericServices_ = value;
       }
     }
+    /// <summary>Gets whether the "py_generic_services" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPyGenericServices {
+      get { return (_hasBits0 & 16) != 0; }
+    }
+    /// <summary>Clears the value of the "py_generic_services" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPyGenericServices() {
+      _hasBits0 &= ~16;
+    }
 
     /// <summary>Field number for the "php_generic_services" field.</summary>
     public const int PhpGenericServicesFieldNumber = 42;
+    private readonly static bool PhpGenericServicesDefaultValue = false;
+
     private bool phpGenericServices_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool PhpGenericServices {
-      get { return phpGenericServices_; }
+      get { if ((_hasBits0 & 512) != 0) { return phpGenericServices_; } else { return PhpGenericServicesDefaultValue; } }
       set {
+        _hasBits0 |= 512;
         phpGenericServices_ = value;
       }
     }
+    /// <summary>Gets whether the "php_generic_services" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPhpGenericServices {
+      get { return (_hasBits0 & 512) != 0; }
+    }
+    /// <summary>Clears the value of the "php_generic_services" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPhpGenericServices() {
+      _hasBits0 &= ~512;
+    }
 
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 23;
+    private readonly static bool DeprecatedDefaultValue = false;
+
     private bool deprecated_;
     /// <summary>
     /// Is this file deprecated?
@@ -3537,14 +4156,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Deprecated {
-      get { return deprecated_; }
+      get { if ((_hasBits0 & 64) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
+        _hasBits0 |= 64;
         deprecated_ = value;
       }
     }
+    /// <summary>Gets whether the "deprecated" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDeprecated {
+      get { return (_hasBits0 & 64) != 0; }
+    }
+    /// <summary>Clears the value of the "deprecated" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDeprecated() {
+      _hasBits0 &= ~64;
+    }
 
     /// <summary>Field number for the "cc_enable_arenas" field.</summary>
     public const int CcEnableArenasFieldNumber = 31;
+    private readonly static bool CcEnableArenasDefaultValue = false;
+
     private bool ccEnableArenas_;
     /// <summary>
     /// Enables the use of arenas for the proto messages in this file. This applies
@@ -3552,44 +4184,81 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool CcEnableArenas {
-      get { return ccEnableArenas_; }
+      get { if ((_hasBits0 & 256) != 0) { return ccEnableArenas_; } else { return CcEnableArenasDefaultValue; } }
       set {
+        _hasBits0 |= 256;
         ccEnableArenas_ = value;
       }
     }
+    /// <summary>Gets whether the "cc_enable_arenas" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasCcEnableArenas {
+      get { return (_hasBits0 & 256) != 0; }
+    }
+    /// <summary>Clears the value of the "cc_enable_arenas" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearCcEnableArenas() {
+      _hasBits0 &= ~256;
+    }
 
     /// <summary>Field number for the "objc_class_prefix" field.</summary>
     public const int ObjcClassPrefixFieldNumber = 36;
-    private string objcClassPrefix_ = "";
+    private readonly static string ObjcClassPrefixDefaultValue = "";
+
+    private string objcClassPrefix_;
     /// <summary>
     /// Sets the objective c class prefix which is prepended to all objective c
     /// generated classes from this .proto. There is no default.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string ObjcClassPrefix {
-      get { return objcClassPrefix_; }
+      get { return objcClassPrefix_ ?? ObjcClassPrefixDefaultValue; }
       set {
         objcClassPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "objc_class_prefix" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasObjcClassPrefix {
+      get { return objcClassPrefix_ != null; }
+    }
+    /// <summary>Clears the value of the "objc_class_prefix" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearObjcClassPrefix() {
+      objcClassPrefix_ = null;
+    }
 
     /// <summary>Field number for the "csharp_namespace" field.</summary>
     public const int CsharpNamespaceFieldNumber = 37;
-    private string csharpNamespace_ = "";
+    private readonly static string CsharpNamespaceDefaultValue = "";
+
+    private string csharpNamespace_;
     /// <summary>
     /// Namespace for generated classes; defaults to the package.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string CsharpNamespace {
-      get { return csharpNamespace_; }
+      get { return csharpNamespace_ ?? CsharpNamespaceDefaultValue; }
       set {
         csharpNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "csharp_namespace" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasCsharpNamespace {
+      get { return csharpNamespace_ != null; }
+    }
+    /// <summary>Clears the value of the "csharp_namespace" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearCsharpNamespace() {
+      csharpNamespace_ = null;
+    }
 
     /// <summary>Field number for the "swift_prefix" field.</summary>
     public const int SwiftPrefixFieldNumber = 39;
-    private string swiftPrefix_ = "";
+    private readonly static string SwiftPrefixDefaultValue = "";
+
+    private string swiftPrefix_;
     /// <summary>
     /// By default Swift generators will take the proto package and CamelCase it
     /// replacing '.' with underscore and use that to prefix the types/symbols
@@ -3598,30 +4267,54 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string SwiftPrefix {
-      get { return swiftPrefix_; }
+      get { return swiftPrefix_ ?? SwiftPrefixDefaultValue; }
       set {
         swiftPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "swift_prefix" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasSwiftPrefix {
+      get { return swiftPrefix_ != null; }
+    }
+    /// <summary>Clears the value of the "swift_prefix" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearSwiftPrefix() {
+      swiftPrefix_ = null;
+    }
 
     /// <summary>Field number for the "php_class_prefix" field.</summary>
     public const int PhpClassPrefixFieldNumber = 40;
-    private string phpClassPrefix_ = "";
+    private readonly static string PhpClassPrefixDefaultValue = "";
+
+    private string phpClassPrefix_;
     /// <summary>
     /// Sets the php class prefix which is prepended to all php generated classes
     /// from this .proto. Default is empty.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string PhpClassPrefix {
-      get { return phpClassPrefix_; }
+      get { return phpClassPrefix_ ?? PhpClassPrefixDefaultValue; }
       set {
         phpClassPrefix_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "php_class_prefix" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPhpClassPrefix {
+      get { return phpClassPrefix_ != null; }
+    }
+    /// <summary>Clears the value of the "php_class_prefix" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPhpClassPrefix() {
+      phpClassPrefix_ = null;
+    }
 
     /// <summary>Field number for the "php_namespace" field.</summary>
     public const int PhpNamespaceFieldNumber = 41;
-    private string phpNamespace_ = "";
+    private readonly static string PhpNamespaceDefaultValue = "";
+
+    private string phpNamespace_;
     /// <summary>
     /// Use this option to change the namespace of php generated classes. Default
     /// is empty. When this option is empty, the package name will be used for
@@ -3629,15 +4322,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string PhpNamespace {
-      get { return phpNamespace_; }
+      get { return phpNamespace_ ?? PhpNamespaceDefaultValue; }
       set {
         phpNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "php_namespace" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPhpNamespace {
+      get { return phpNamespace_ != null; }
+    }
+    /// <summary>Clears the value of the "php_namespace" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPhpNamespace() {
+      phpNamespace_ = null;
+    }
 
     /// <summary>Field number for the "php_metadata_namespace" field.</summary>
     public const int PhpMetadataNamespaceFieldNumber = 44;
-    private string phpMetadataNamespace_ = "";
+    private readonly static string PhpMetadataNamespaceDefaultValue = "";
+
+    private string phpMetadataNamespace_;
     /// <summary>
     /// Use this option to change the namespace of php generated metadata classes.
     /// Default is empty. When this option is empty, the proto file name will be used
@@ -3645,15 +4350,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string PhpMetadataNamespace {
-      get { return phpMetadataNamespace_; }
+      get { return phpMetadataNamespace_ ?? PhpMetadataNamespaceDefaultValue; }
       set {
         phpMetadataNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "php_metadata_namespace" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPhpMetadataNamespace {
+      get { return phpMetadataNamespace_ != null; }
+    }
+    /// <summary>Clears the value of the "php_metadata_namespace" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPhpMetadataNamespace() {
+      phpMetadataNamespace_ = null;
+    }
 
     /// <summary>Field number for the "ruby_package" field.</summary>
     public const int RubyPackageFieldNumber = 45;
-    private string rubyPackage_ = "";
+    private readonly static string RubyPackageDefaultValue = "";
+
+    private string rubyPackage_;
     /// <summary>
     /// Use this option to change the package of ruby generated classes. Default
     /// is empty. When this option is not set, the package name will be used for
@@ -3661,11 +4378,21 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string RubyPackage {
-      get { return rubyPackage_; }
+      get { return rubyPackage_ ?? RubyPackageDefaultValue; }
       set {
         rubyPackage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "ruby_package" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasRubyPackage {
+      get { return rubyPackage_ != null; }
+    }
+    /// <summary>Clears the value of the "ruby_package" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearRubyPackage() {
+      rubyPackage_ = null;
+    }
 
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
@@ -3721,26 +4448,26 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (JavaPackage.Length != 0) hash ^= JavaPackage.GetHashCode();
-      if (JavaOuterClassname.Length != 0) hash ^= JavaOuterClassname.GetHashCode();
-      if (JavaMultipleFiles != false) hash ^= JavaMultipleFiles.GetHashCode();
-      if (JavaGenerateEqualsAndHash != false) hash ^= JavaGenerateEqualsAndHash.GetHashCode();
-      if (JavaStringCheckUtf8 != false) hash ^= JavaStringCheckUtf8.GetHashCode();
-      if (OptimizeFor != 0) hash ^= OptimizeFor.GetHashCode();
-      if (GoPackage.Length != 0) hash ^= GoPackage.GetHashCode();
-      if (CcGenericServices != false) hash ^= CcGenericServices.GetHashCode();
-      if (JavaGenericServices != false) hash ^= JavaGenericServices.GetHashCode();
-      if (PyGenericServices != false) hash ^= PyGenericServices.GetHashCode();
-      if (PhpGenericServices != false) hash ^= PhpGenericServices.GetHashCode();
-      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
-      if (CcEnableArenas != false) hash ^= CcEnableArenas.GetHashCode();
-      if (ObjcClassPrefix.Length != 0) hash ^= ObjcClassPrefix.GetHashCode();
-      if (CsharpNamespace.Length != 0) hash ^= CsharpNamespace.GetHashCode();
-      if (SwiftPrefix.Length != 0) hash ^= SwiftPrefix.GetHashCode();
-      if (PhpClassPrefix.Length != 0) hash ^= PhpClassPrefix.GetHashCode();
-      if (PhpNamespace.Length != 0) hash ^= PhpNamespace.GetHashCode();
-      if (PhpMetadataNamespace.Length != 0) hash ^= PhpMetadataNamespace.GetHashCode();
-      if (RubyPackage.Length != 0) hash ^= RubyPackage.GetHashCode();
+      if (HasJavaPackage) hash ^= JavaPackage.GetHashCode();
+      if (HasJavaOuterClassname) hash ^= JavaOuterClassname.GetHashCode();
+      if (HasJavaMultipleFiles) hash ^= JavaMultipleFiles.GetHashCode();
+      if (HasJavaGenerateEqualsAndHash) hash ^= JavaGenerateEqualsAndHash.GetHashCode();
+      if (HasJavaStringCheckUtf8) hash ^= JavaStringCheckUtf8.GetHashCode();
+      if (HasOptimizeFor) hash ^= OptimizeFor.GetHashCode();
+      if (HasGoPackage) hash ^= GoPackage.GetHashCode();
+      if (HasCcGenericServices) hash ^= CcGenericServices.GetHashCode();
+      if (HasJavaGenericServices) hash ^= JavaGenericServices.GetHashCode();
+      if (HasPyGenericServices) hash ^= PyGenericServices.GetHashCode();
+      if (HasPhpGenericServices) hash ^= PhpGenericServices.GetHashCode();
+      if (HasDeprecated) hash ^= Deprecated.GetHashCode();
+      if (HasCcEnableArenas) hash ^= CcEnableArenas.GetHashCode();
+      if (HasObjcClassPrefix) hash ^= ObjcClassPrefix.GetHashCode();
+      if (HasCsharpNamespace) hash ^= CsharpNamespace.GetHashCode();
+      if (HasSwiftPrefix) hash ^= SwiftPrefix.GetHashCode();
+      if (HasPhpClassPrefix) hash ^= PhpClassPrefix.GetHashCode();
+      if (HasPhpNamespace) hash ^= PhpNamespace.GetHashCode();
+      if (HasPhpMetadataNamespace) hash ^= PhpMetadataNamespace.GetHashCode();
+      if (HasRubyPackage) hash ^= RubyPackage.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -3755,83 +4482,83 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (JavaPackage.Length != 0) {
+      if (HasJavaPackage) {
         output.WriteRawTag(10);
         output.WriteString(JavaPackage);
       }
-      if (JavaOuterClassname.Length != 0) {
+      if (HasJavaOuterClassname) {
         output.WriteRawTag(66);
         output.WriteString(JavaOuterClassname);
       }
-      if (OptimizeFor != 0) {
+      if (HasOptimizeFor) {
         output.WriteRawTag(72);
         output.WriteEnum((int) OptimizeFor);
       }
-      if (JavaMultipleFiles != false) {
+      if (HasJavaMultipleFiles) {
         output.WriteRawTag(80);
         output.WriteBool(JavaMultipleFiles);
       }
-      if (GoPackage.Length != 0) {
+      if (HasGoPackage) {
         output.WriteRawTag(90);
         output.WriteString(GoPackage);
       }
-      if (CcGenericServices != false) {
+      if (HasCcGenericServices) {
         output.WriteRawTag(128, 1);
         output.WriteBool(CcGenericServices);
       }
-      if (JavaGenericServices != false) {
+      if (HasJavaGenericServices) {
         output.WriteRawTag(136, 1);
         output.WriteBool(JavaGenericServices);
       }
-      if (PyGenericServices != false) {
+      if (HasPyGenericServices) {
         output.WriteRawTag(144, 1);
         output.WriteBool(PyGenericServices);
       }
-      if (JavaGenerateEqualsAndHash != false) {
+      if (HasJavaGenerateEqualsAndHash) {
         output.WriteRawTag(160, 1);
         output.WriteBool(JavaGenerateEqualsAndHash);
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         output.WriteRawTag(184, 1);
         output.WriteBool(Deprecated);
       }
-      if (JavaStringCheckUtf8 != false) {
+      if (HasJavaStringCheckUtf8) {
         output.WriteRawTag(216, 1);
         output.WriteBool(JavaStringCheckUtf8);
       }
-      if (CcEnableArenas != false) {
+      if (HasCcEnableArenas) {
         output.WriteRawTag(248, 1);
         output.WriteBool(CcEnableArenas);
       }
-      if (ObjcClassPrefix.Length != 0) {
+      if (HasObjcClassPrefix) {
         output.WriteRawTag(162, 2);
         output.WriteString(ObjcClassPrefix);
       }
-      if (CsharpNamespace.Length != 0) {
+      if (HasCsharpNamespace) {
         output.WriteRawTag(170, 2);
         output.WriteString(CsharpNamespace);
       }
-      if (SwiftPrefix.Length != 0) {
+      if (HasSwiftPrefix) {
         output.WriteRawTag(186, 2);
         output.WriteString(SwiftPrefix);
       }
-      if (PhpClassPrefix.Length != 0) {
+      if (HasPhpClassPrefix) {
         output.WriteRawTag(194, 2);
         output.WriteString(PhpClassPrefix);
       }
-      if (PhpNamespace.Length != 0) {
+      if (HasPhpNamespace) {
         output.WriteRawTag(202, 2);
         output.WriteString(PhpNamespace);
       }
-      if (PhpGenericServices != false) {
+      if (HasPhpGenericServices) {
         output.WriteRawTag(208, 2);
         output.WriteBool(PhpGenericServices);
       }
-      if (PhpMetadataNamespace.Length != 0) {
+      if (HasPhpMetadataNamespace) {
         output.WriteRawTag(226, 2);
         output.WriteString(PhpMetadataNamespace);
       }
-      if (RubyPackage.Length != 0) {
+      if (HasRubyPackage) {
         output.WriteRawTag(234, 2);
         output.WriteString(RubyPackage);
       }
@@ -3844,64 +4571,64 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (JavaPackage.Length != 0) {
+      if (HasJavaPackage) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(JavaPackage);
       }
-      if (JavaOuterClassname.Length != 0) {
+      if (HasJavaOuterClassname) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(JavaOuterClassname);
       }
-      if (JavaMultipleFiles != false) {
+      if (HasJavaMultipleFiles) {
         size += 1 + 1;
       }
-      if (JavaGenerateEqualsAndHash != false) {
+      if (HasJavaGenerateEqualsAndHash) {
         size += 2 + 1;
       }
-      if (JavaStringCheckUtf8 != false) {
+      if (HasJavaStringCheckUtf8) {
         size += 2 + 1;
       }
-      if (OptimizeFor != 0) {
+      if (HasOptimizeFor) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) OptimizeFor);
       }
-      if (GoPackage.Length != 0) {
+      if (HasGoPackage) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(GoPackage);
       }
-      if (CcGenericServices != false) {
+      if (HasCcGenericServices) {
         size += 2 + 1;
       }
-      if (JavaGenericServices != false) {
+      if (HasJavaGenericServices) {
         size += 2 + 1;
       }
-      if (PyGenericServices != false) {
+      if (HasPyGenericServices) {
         size += 2 + 1;
       }
-      if (PhpGenericServices != false) {
+      if (HasPhpGenericServices) {
         size += 2 + 1;
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         size += 2 + 1;
       }
-      if (CcEnableArenas != false) {
+      if (HasCcEnableArenas) {
         size += 2 + 1;
       }
-      if (ObjcClassPrefix.Length != 0) {
+      if (HasObjcClassPrefix) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(ObjcClassPrefix);
       }
-      if (CsharpNamespace.Length != 0) {
+      if (HasCsharpNamespace) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(CsharpNamespace);
       }
-      if (SwiftPrefix.Length != 0) {
+      if (HasSwiftPrefix) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(SwiftPrefix);
       }
-      if (PhpClassPrefix.Length != 0) {
+      if (HasPhpClassPrefix) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpClassPrefix);
       }
-      if (PhpNamespace.Length != 0) {
+      if (HasPhpNamespace) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpNamespace);
       }
-      if (PhpMetadataNamespace.Length != 0) {
+      if (HasPhpMetadataNamespace) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpMetadataNamespace);
       }
-      if (RubyPackage.Length != 0) {
+      if (HasRubyPackage) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(RubyPackage);
       }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -3916,64 +4643,64 @@
       if (other == null) {
         return;
       }
-      if (other.JavaPackage.Length != 0) {
+      if (other.HasJavaPackage) {
         JavaPackage = other.JavaPackage;
       }
-      if (other.JavaOuterClassname.Length != 0) {
+      if (other.HasJavaOuterClassname) {
         JavaOuterClassname = other.JavaOuterClassname;
       }
-      if (other.JavaMultipleFiles != false) {
+      if (other.HasJavaMultipleFiles) {
         JavaMultipleFiles = other.JavaMultipleFiles;
       }
-      if (other.JavaGenerateEqualsAndHash != false) {
+      if (other.HasJavaGenerateEqualsAndHash) {
         JavaGenerateEqualsAndHash = other.JavaGenerateEqualsAndHash;
       }
-      if (other.JavaStringCheckUtf8 != false) {
+      if (other.HasJavaStringCheckUtf8) {
         JavaStringCheckUtf8 = other.JavaStringCheckUtf8;
       }
-      if (other.OptimizeFor != 0) {
+      if (other.HasOptimizeFor) {
         OptimizeFor = other.OptimizeFor;
       }
-      if (other.GoPackage.Length != 0) {
+      if (other.HasGoPackage) {
         GoPackage = other.GoPackage;
       }
-      if (other.CcGenericServices != false) {
+      if (other.HasCcGenericServices) {
         CcGenericServices = other.CcGenericServices;
       }
-      if (other.JavaGenericServices != false) {
+      if (other.HasJavaGenericServices) {
         JavaGenericServices = other.JavaGenericServices;
       }
-      if (other.PyGenericServices != false) {
+      if (other.HasPyGenericServices) {
         PyGenericServices = other.PyGenericServices;
       }
-      if (other.PhpGenericServices != false) {
+      if (other.HasPhpGenericServices) {
         PhpGenericServices = other.PhpGenericServices;
       }
-      if (other.Deprecated != false) {
+      if (other.HasDeprecated) {
         Deprecated = other.Deprecated;
       }
-      if (other.CcEnableArenas != false) {
+      if (other.HasCcEnableArenas) {
         CcEnableArenas = other.CcEnableArenas;
       }
-      if (other.ObjcClassPrefix.Length != 0) {
+      if (other.HasObjcClassPrefix) {
         ObjcClassPrefix = other.ObjcClassPrefix;
       }
-      if (other.CsharpNamespace.Length != 0) {
+      if (other.HasCsharpNamespace) {
         CsharpNamespace = other.CsharpNamespace;
       }
-      if (other.SwiftPrefix.Length != 0) {
+      if (other.HasSwiftPrefix) {
         SwiftPrefix = other.SwiftPrefix;
       }
-      if (other.PhpClassPrefix.Length != 0) {
+      if (other.HasPhpClassPrefix) {
         PhpClassPrefix = other.PhpClassPrefix;
       }
-      if (other.PhpNamespace.Length != 0) {
+      if (other.HasPhpNamespace) {
         PhpNamespace = other.PhpNamespace;
       }
-      if (other.PhpMetadataNamespace.Length != 0) {
+      if (other.HasPhpMetadataNamespace) {
         PhpMetadataNamespace = other.PhpMetadataNamespace;
       }
-      if (other.RubyPackage.Length != 0) {
+      if (other.HasRubyPackage) {
         RubyPackage = other.RubyPackage;
       }
       uninterpretedOption_.Add(other.uninterpretedOption_);
@@ -3997,7 +4724,7 @@
             break;
           }
           case 72: {
-            optimizeFor_ = (global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) input.ReadEnum();
+            OptimizeFor = (global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) input.ReadEnum();
             break;
           }
           case 80: {
@@ -4106,6 +4833,7 @@
   internal sealed partial class MessageOptions : pb::IMessage<MessageOptions> {
     private static readonly pb::MessageParser<MessageOptions> _parser = new pb::MessageParser<MessageOptions>(() => new MessageOptions());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MessageOptions> Parser { get { return _parser; } }
 
@@ -4130,6 +4858,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public MessageOptions(MessageOptions other) : this() {
+      _hasBits0 = other._hasBits0;
       messageSetWireFormat_ = other.messageSetWireFormat_;
       noStandardDescriptorAccessor_ = other.noStandardDescriptorAccessor_;
       deprecated_ = other.deprecated_;
@@ -4145,6 +4874,8 @@
 
     /// <summary>Field number for the "message_set_wire_format" field.</summary>
     public const int MessageSetWireFormatFieldNumber = 1;
+    private readonly static bool MessageSetWireFormatDefaultValue = false;
+
     private bool messageSetWireFormat_;
     /// <summary>
     /// Set true to use the old proto1 MessageSet wire format for extensions.
@@ -4168,14 +4899,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool MessageSetWireFormat {
-      get { return messageSetWireFormat_; }
+      get { if ((_hasBits0 & 1) != 0) { return messageSetWireFormat_; } else { return MessageSetWireFormatDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         messageSetWireFormat_ = value;
       }
     }
+    /// <summary>Gets whether the "message_set_wire_format" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasMessageSetWireFormat {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "message_set_wire_format" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearMessageSetWireFormat() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "no_standard_descriptor_accessor" field.</summary>
     public const int NoStandardDescriptorAccessorFieldNumber = 2;
+    private readonly static bool NoStandardDescriptorAccessorDefaultValue = false;
+
     private bool noStandardDescriptorAccessor_;
     /// <summary>
     /// Disables the generation of the standard "descriptor()" accessor, which can
@@ -4184,14 +4928,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool NoStandardDescriptorAccessor {
-      get { return noStandardDescriptorAccessor_; }
+      get { if ((_hasBits0 & 2) != 0) { return noStandardDescriptorAccessor_; } else { return NoStandardDescriptorAccessorDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         noStandardDescriptorAccessor_ = value;
       }
     }
+    /// <summary>Gets whether the "no_standard_descriptor_accessor" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasNoStandardDescriptorAccessor {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "no_standard_descriptor_accessor" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearNoStandardDescriptorAccessor() {
+      _hasBits0 &= ~2;
+    }
 
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 3;
+    private readonly static bool DeprecatedDefaultValue = false;
+
     private bool deprecated_;
     /// <summary>
     /// Is this message deprecated?
@@ -4201,14 +4958,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Deprecated {
-      get { return deprecated_; }
+      get { if ((_hasBits0 & 4) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
+        _hasBits0 |= 4;
         deprecated_ = value;
       }
     }
+    /// <summary>Gets whether the "deprecated" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDeprecated {
+      get { return (_hasBits0 & 4) != 0; }
+    }
+    /// <summary>Clears the value of the "deprecated" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDeprecated() {
+      _hasBits0 &= ~4;
+    }
 
     /// <summary>Field number for the "map_entry" field.</summary>
     public const int MapEntryFieldNumber = 7;
+    private readonly static bool MapEntryDefaultValue = false;
+
     private bool mapEntry_;
     /// <summary>
     /// Whether the message is an automatically generated map entry type for the
@@ -4235,11 +5005,22 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool MapEntry {
-      get { return mapEntry_; }
+      get { if ((_hasBits0 & 8) != 0) { return mapEntry_; } else { return MapEntryDefaultValue; } }
       set {
+        _hasBits0 |= 8;
         mapEntry_ = value;
       }
     }
+    /// <summary>Gets whether the "map_entry" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasMapEntry {
+      get { return (_hasBits0 & 8) != 0; }
+    }
+    /// <summary>Clears the value of the "map_entry" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearMapEntry() {
+      _hasBits0 &= ~8;
+    }
 
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
@@ -4278,10 +5059,10 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (MessageSetWireFormat != false) hash ^= MessageSetWireFormat.GetHashCode();
-      if (NoStandardDescriptorAccessor != false) hash ^= NoStandardDescriptorAccessor.GetHashCode();
-      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
-      if (MapEntry != false) hash ^= MapEntry.GetHashCode();
+      if (HasMessageSetWireFormat) hash ^= MessageSetWireFormat.GetHashCode();
+      if (HasNoStandardDescriptorAccessor) hash ^= NoStandardDescriptorAccessor.GetHashCode();
+      if (HasDeprecated) hash ^= Deprecated.GetHashCode();
+      if (HasMapEntry) hash ^= MapEntry.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -4296,19 +5077,19 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (MessageSetWireFormat != false) {
+      if (HasMessageSetWireFormat) {
         output.WriteRawTag(8);
         output.WriteBool(MessageSetWireFormat);
       }
-      if (NoStandardDescriptorAccessor != false) {
+      if (HasNoStandardDescriptorAccessor) {
         output.WriteRawTag(16);
         output.WriteBool(NoStandardDescriptorAccessor);
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         output.WriteRawTag(24);
         output.WriteBool(Deprecated);
       }
-      if (MapEntry != false) {
+      if (HasMapEntry) {
         output.WriteRawTag(56);
         output.WriteBool(MapEntry);
       }
@@ -4321,16 +5102,16 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (MessageSetWireFormat != false) {
+      if (HasMessageSetWireFormat) {
         size += 1 + 1;
       }
-      if (NoStandardDescriptorAccessor != false) {
+      if (HasNoStandardDescriptorAccessor) {
         size += 1 + 1;
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         size += 1 + 1;
       }
-      if (MapEntry != false) {
+      if (HasMapEntry) {
         size += 1 + 1;
       }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -4345,16 +5126,16 @@
       if (other == null) {
         return;
       }
-      if (other.MessageSetWireFormat != false) {
+      if (other.HasMessageSetWireFormat) {
         MessageSetWireFormat = other.MessageSetWireFormat;
       }
-      if (other.NoStandardDescriptorAccessor != false) {
+      if (other.HasNoStandardDescriptorAccessor) {
         NoStandardDescriptorAccessor = other.NoStandardDescriptorAccessor;
       }
-      if (other.Deprecated != false) {
+      if (other.HasDeprecated) {
         Deprecated = other.Deprecated;
       }
-      if (other.MapEntry != false) {
+      if (other.HasMapEntry) {
         MapEntry = other.MapEntry;
       }
       uninterpretedOption_.Add(other.uninterpretedOption_);
@@ -4398,6 +5179,7 @@
   internal sealed partial class FieldOptions : pb::IMessage<FieldOptions> {
     private static readonly pb::MessageParser<FieldOptions> _parser = new pb::MessageParser<FieldOptions>(() => new FieldOptions());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FieldOptions> Parser { get { return _parser; } }
 
@@ -4422,6 +5204,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FieldOptions(FieldOptions other) : this() {
+      _hasBits0 = other._hasBits0;
       ctype_ = other.ctype_;
       packed_ = other.packed_;
       jstype_ = other.jstype_;
@@ -4439,7 +5222,9 @@
 
     /// <summary>Field number for the "ctype" field.</summary>
     public const int CtypeFieldNumber = 1;
-    private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_ = 0;
+    private readonly static global::Google.Protobuf.Reflection.FieldOptions.Types.CType CtypeDefaultValue = global::Google.Protobuf.Reflection.FieldOptions.Types.CType.String;
+
+    private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_;
     /// <summary>
     /// The ctype option instructs the C++ code generator to use a different
     /// representation of the field than it normally would.  See the specific
@@ -4448,14 +5233,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public global::Google.Protobuf.Reflection.FieldOptions.Types.CType Ctype {
-      get { return ctype_; }
+      get { if ((_hasBits0 & 1) != 0) { return ctype_; } else { return CtypeDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         ctype_ = value;
       }
     }
+    /// <summary>Gets whether the "ctype" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasCtype {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "ctype" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearCtype() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "packed" field.</summary>
     public const int PackedFieldNumber = 2;
+    private readonly static bool PackedDefaultValue = false;
+
     private bool packed_;
     /// <summary>
     /// The packed option can be enabled for repeated primitive fields to enable
@@ -4466,15 +5264,28 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Packed {
-      get { return packed_; }
+      get { if ((_hasBits0 & 2) != 0) { return packed_; } else { return PackedDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         packed_ = value;
       }
     }
+    /// <summary>Gets whether the "packed" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPacked {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "packed" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPacked() {
+      _hasBits0 &= ~2;
+    }
 
     /// <summary>Field number for the "jstype" field.</summary>
     public const int JstypeFieldNumber = 6;
-    private global::Google.Protobuf.Reflection.FieldOptions.Types.JSType jstype_ = 0;
+    private readonly static global::Google.Protobuf.Reflection.FieldOptions.Types.JSType JstypeDefaultValue = global::Google.Protobuf.Reflection.FieldOptions.Types.JSType.JsNormal;
+
+    private global::Google.Protobuf.Reflection.FieldOptions.Types.JSType jstype_;
     /// <summary>
     /// The jstype option determines the JavaScript type used for values of the
     /// field.  The option is permitted only for 64 bit integral and fixed types
@@ -4490,14 +5301,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public global::Google.Protobuf.Reflection.FieldOptions.Types.JSType Jstype {
-      get { return jstype_; }
+      get { if ((_hasBits0 & 16) != 0) { return jstype_; } else { return JstypeDefaultValue; } }
       set {
+        _hasBits0 |= 16;
         jstype_ = value;
       }
     }
+    /// <summary>Gets whether the "jstype" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasJstype {
+      get { return (_hasBits0 & 16) != 0; }
+    }
+    /// <summary>Clears the value of the "jstype" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearJstype() {
+      _hasBits0 &= ~16;
+    }
 
     /// <summary>Field number for the "lazy" field.</summary>
     public const int LazyFieldNumber = 5;
+    private readonly static bool LazyDefaultValue = false;
+
     private bool lazy_;
     /// <summary>
     /// Should this field be parsed lazily?  Lazy applies only to message-type
@@ -4530,14 +5354,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Lazy {
-      get { return lazy_; }
+      get { if ((_hasBits0 & 8) != 0) { return lazy_; } else { return LazyDefaultValue; } }
       set {
+        _hasBits0 |= 8;
         lazy_ = value;
       }
     }
+    /// <summary>Gets whether the "lazy" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasLazy {
+      get { return (_hasBits0 & 8) != 0; }
+    }
+    /// <summary>Clears the value of the "lazy" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearLazy() {
+      _hasBits0 &= ~8;
+    }
 
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 3;
+    private readonly static bool DeprecatedDefaultValue = false;
+
     private bool deprecated_;
     /// <summary>
     /// Is this field deprecated?
@@ -4547,25 +5384,49 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Deprecated {
-      get { return deprecated_; }
+      get { if ((_hasBits0 & 4) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
+        _hasBits0 |= 4;
         deprecated_ = value;
       }
     }
+    /// <summary>Gets whether the "deprecated" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDeprecated {
+      get { return (_hasBits0 & 4) != 0; }
+    }
+    /// <summary>Clears the value of the "deprecated" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDeprecated() {
+      _hasBits0 &= ~4;
+    }
 
     /// <summary>Field number for the "weak" field.</summary>
     public const int WeakFieldNumber = 10;
+    private readonly static bool WeakDefaultValue = false;
+
     private bool weak_;
     /// <summary>
     /// For Google-internal migration only. Do not use.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Weak {
-      get { return weak_; }
+      get { if ((_hasBits0 & 32) != 0) { return weak_; } else { return WeakDefaultValue; } }
       set {
+        _hasBits0 |= 32;
         weak_ = value;
       }
     }
+    /// <summary>Gets whether the "weak" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasWeak {
+      get { return (_hasBits0 & 32) != 0; }
+    }
+    /// <summary>Clears the value of the "weak" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearWeak() {
+      _hasBits0 &= ~32;
+    }
 
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
@@ -4606,12 +5467,12 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Ctype != 0) hash ^= Ctype.GetHashCode();
-      if (Packed != false) hash ^= Packed.GetHashCode();
-      if (Jstype != 0) hash ^= Jstype.GetHashCode();
-      if (Lazy != false) hash ^= Lazy.GetHashCode();
-      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
-      if (Weak != false) hash ^= Weak.GetHashCode();
+      if (HasCtype) hash ^= Ctype.GetHashCode();
+      if (HasPacked) hash ^= Packed.GetHashCode();
+      if (HasJstype) hash ^= Jstype.GetHashCode();
+      if (HasLazy) hash ^= Lazy.GetHashCode();
+      if (HasDeprecated) hash ^= Deprecated.GetHashCode();
+      if (HasWeak) hash ^= Weak.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -4626,27 +5487,27 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Ctype != 0) {
+      if (HasCtype) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Ctype);
       }
-      if (Packed != false) {
+      if (HasPacked) {
         output.WriteRawTag(16);
         output.WriteBool(Packed);
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         output.WriteRawTag(24);
         output.WriteBool(Deprecated);
       }
-      if (Lazy != false) {
+      if (HasLazy) {
         output.WriteRawTag(40);
         output.WriteBool(Lazy);
       }
-      if (Jstype != 0) {
+      if (HasJstype) {
         output.WriteRawTag(48);
         output.WriteEnum((int) Jstype);
       }
-      if (Weak != false) {
+      if (HasWeak) {
         output.WriteRawTag(80);
         output.WriteBool(Weak);
       }
@@ -4659,22 +5520,22 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Ctype != 0) {
+      if (HasCtype) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Ctype);
       }
-      if (Packed != false) {
+      if (HasPacked) {
         size += 1 + 1;
       }
-      if (Jstype != 0) {
+      if (HasJstype) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Jstype);
       }
-      if (Lazy != false) {
+      if (HasLazy) {
         size += 1 + 1;
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         size += 1 + 1;
       }
-      if (Weak != false) {
+      if (HasWeak) {
         size += 1 + 1;
       }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -4689,22 +5550,22 @@
       if (other == null) {
         return;
       }
-      if (other.Ctype != 0) {
+      if (other.HasCtype) {
         Ctype = other.Ctype;
       }
-      if (other.Packed != false) {
+      if (other.HasPacked) {
         Packed = other.Packed;
       }
-      if (other.Jstype != 0) {
+      if (other.HasJstype) {
         Jstype = other.Jstype;
       }
-      if (other.Lazy != false) {
+      if (other.HasLazy) {
         Lazy = other.Lazy;
       }
-      if (other.Deprecated != false) {
+      if (other.HasDeprecated) {
         Deprecated = other.Deprecated;
       }
-      if (other.Weak != false) {
+      if (other.HasWeak) {
         Weak = other.Weak;
       }
       uninterpretedOption_.Add(other.uninterpretedOption_);
@@ -4720,7 +5581,7 @@
             CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);
             break;
           case 8: {
-            ctype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum();
+            Ctype = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum();
             break;
           }
           case 16: {
@@ -4736,7 +5597,7 @@
             break;
           }
           case 48: {
-            jstype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) input.ReadEnum();
+            Jstype = (global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) input.ReadEnum();
             break;
           }
           case 80: {
@@ -4913,6 +5774,7 @@
   internal sealed partial class EnumOptions : pb::IMessage<EnumOptions> {
     private static readonly pb::MessageParser<EnumOptions> _parser = new pb::MessageParser<EnumOptions>(() => new EnumOptions());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EnumOptions> Parser { get { return _parser; } }
 
@@ -4937,6 +5799,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public EnumOptions(EnumOptions other) : this() {
+      _hasBits0 = other._hasBits0;
       allowAlias_ = other.allowAlias_;
       deprecated_ = other.deprecated_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
@@ -4950,6 +5813,8 @@
 
     /// <summary>Field number for the "allow_alias" field.</summary>
     public const int AllowAliasFieldNumber = 2;
+    private readonly static bool AllowAliasDefaultValue = false;
+
     private bool allowAlias_;
     /// <summary>
     /// Set this option to true to allow mapping different tag names to the same
@@ -4957,14 +5822,27 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool AllowAlias {
-      get { return allowAlias_; }
+      get { if ((_hasBits0 & 1) != 0) { return allowAlias_; } else { return AllowAliasDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         allowAlias_ = value;
       }
     }
+    /// <summary>Gets whether the "allow_alias" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasAllowAlias {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "allow_alias" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearAllowAlias() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 3;
+    private readonly static bool DeprecatedDefaultValue = false;
+
     private bool deprecated_;
     /// <summary>
     /// Is this enum deprecated?
@@ -4974,11 +5852,22 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Deprecated {
-      get { return deprecated_; }
+      get { if ((_hasBits0 & 2) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         deprecated_ = value;
       }
     }
+    /// <summary>Gets whether the "deprecated" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDeprecated {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "deprecated" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDeprecated() {
+      _hasBits0 &= ~2;
+    }
 
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
@@ -5015,8 +5904,8 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (AllowAlias != false) hash ^= AllowAlias.GetHashCode();
-      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      if (HasAllowAlias) hash ^= AllowAlias.GetHashCode();
+      if (HasDeprecated) hash ^= Deprecated.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -5031,11 +5920,11 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (AllowAlias != false) {
+      if (HasAllowAlias) {
         output.WriteRawTag(16);
         output.WriteBool(AllowAlias);
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         output.WriteRawTag(24);
         output.WriteBool(Deprecated);
       }
@@ -5048,10 +5937,10 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (AllowAlias != false) {
+      if (HasAllowAlias) {
         size += 1 + 1;
       }
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         size += 1 + 1;
       }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -5066,10 +5955,10 @@
       if (other == null) {
         return;
       }
-      if (other.AllowAlias != false) {
+      if (other.HasAllowAlias) {
         AllowAlias = other.AllowAlias;
       }
-      if (other.Deprecated != false) {
+      if (other.HasDeprecated) {
         Deprecated = other.Deprecated;
       }
       uninterpretedOption_.Add(other.uninterpretedOption_);
@@ -5105,6 +5994,7 @@
   internal sealed partial class EnumValueOptions : pb::IMessage<EnumValueOptions> {
     private static readonly pb::MessageParser<EnumValueOptions> _parser = new pb::MessageParser<EnumValueOptions>(() => new EnumValueOptions());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EnumValueOptions> Parser { get { return _parser; } }
 
@@ -5129,6 +6019,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public EnumValueOptions(EnumValueOptions other) : this() {
+      _hasBits0 = other._hasBits0;
       deprecated_ = other.deprecated_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -5141,6 +6032,8 @@
 
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 1;
+    private readonly static bool DeprecatedDefaultValue = false;
+
     private bool deprecated_;
     /// <summary>
     /// Is this enum value deprecated?
@@ -5150,11 +6043,22 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Deprecated {
-      get { return deprecated_; }
+      get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         deprecated_ = value;
       }
     }
+    /// <summary>Gets whether the "deprecated" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDeprecated {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "deprecated" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDeprecated() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
@@ -5190,7 +6094,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      if (HasDeprecated) hash ^= Deprecated.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -5205,7 +6109,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         output.WriteRawTag(8);
         output.WriteBool(Deprecated);
       }
@@ -5218,7 +6122,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         size += 1 + 1;
       }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -5233,7 +6137,7 @@
       if (other == null) {
         return;
       }
-      if (other.Deprecated != false) {
+      if (other.HasDeprecated) {
         Deprecated = other.Deprecated;
       }
       uninterpretedOption_.Add(other.uninterpretedOption_);
@@ -5265,6 +6169,7 @@
   internal sealed partial class ServiceOptions : pb::IMessage<ServiceOptions> {
     private static readonly pb::MessageParser<ServiceOptions> _parser = new pb::MessageParser<ServiceOptions>(() => new ServiceOptions());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServiceOptions> Parser { get { return _parser; } }
 
@@ -5289,6 +6194,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ServiceOptions(ServiceOptions other) : this() {
+      _hasBits0 = other._hasBits0;
       deprecated_ = other.deprecated_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -5301,6 +6207,8 @@
 
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 33;
+    private readonly static bool DeprecatedDefaultValue = false;
+
     private bool deprecated_;
     /// <summary>
     /// Is this service deprecated?
@@ -5310,11 +6218,22 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Deprecated {
-      get { return deprecated_; }
+      get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         deprecated_ = value;
       }
     }
+    /// <summary>Gets whether the "deprecated" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDeprecated {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "deprecated" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDeprecated() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
@@ -5350,7 +6269,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
+      if (HasDeprecated) hash ^= Deprecated.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -5365,7 +6284,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         output.WriteRawTag(136, 2);
         output.WriteBool(Deprecated);
       }
@@ -5378,7 +6297,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         size += 2 + 1;
       }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -5393,7 +6312,7 @@
       if (other == null) {
         return;
       }
-      if (other.Deprecated != false) {
+      if (other.HasDeprecated) {
         Deprecated = other.Deprecated;
       }
       uninterpretedOption_.Add(other.uninterpretedOption_);
@@ -5425,6 +6344,7 @@
   internal sealed partial class MethodOptions : pb::IMessage<MethodOptions> {
     private static readonly pb::MessageParser<MethodOptions> _parser = new pb::MessageParser<MethodOptions>(() => new MethodOptions());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<MethodOptions> Parser { get { return _parser; } }
 
@@ -5449,6 +6369,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public MethodOptions(MethodOptions other) : this() {
+      _hasBits0 = other._hasBits0;
       deprecated_ = other.deprecated_;
       idempotencyLevel_ = other.idempotencyLevel_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
@@ -5462,6 +6383,8 @@
 
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 33;
+    private readonly static bool DeprecatedDefaultValue = false;
+
     private bool deprecated_;
     /// <summary>
     /// Is this method deprecated?
@@ -5471,22 +6394,46 @@
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public bool Deprecated {
-      get { return deprecated_; }
+      get { if ((_hasBits0 & 1) != 0) { return deprecated_; } else { return DeprecatedDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         deprecated_ = value;
       }
     }
+    /// <summary>Gets whether the "deprecated" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDeprecated {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "deprecated" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDeprecated() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "idempotency_level" field.</summary>
     public const int IdempotencyLevelFieldNumber = 34;
-    private global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel idempotencyLevel_ = 0;
+    private readonly static global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel IdempotencyLevelDefaultValue = global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel.IdempotencyUnknown;
+
+    private global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel idempotencyLevel_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel IdempotencyLevel {
-      get { return idempotencyLevel_; }
+      get { if ((_hasBits0 & 2) != 0) { return idempotencyLevel_; } else { return IdempotencyLevelDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         idempotencyLevel_ = value;
       }
     }
+    /// <summary>Gets whether the "idempotency_level" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasIdempotencyLevel {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "idempotency_level" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearIdempotencyLevel() {
+      _hasBits0 &= ~2;
+    }
 
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
@@ -5523,8 +6470,8 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Deprecated != false) hash ^= Deprecated.GetHashCode();
-      if (IdempotencyLevel != 0) hash ^= IdempotencyLevel.GetHashCode();
+      if (HasDeprecated) hash ^= Deprecated.GetHashCode();
+      if (HasIdempotencyLevel) hash ^= IdempotencyLevel.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
@@ -5539,11 +6486,11 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         output.WriteRawTag(136, 2);
         output.WriteBool(Deprecated);
       }
-      if (IdempotencyLevel != 0) {
+      if (HasIdempotencyLevel) {
         output.WriteRawTag(144, 2);
         output.WriteEnum((int) IdempotencyLevel);
       }
@@ -5556,10 +6503,10 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
-      if (Deprecated != false) {
+      if (HasDeprecated) {
         size += 2 + 1;
       }
-      if (IdempotencyLevel != 0) {
+      if (HasIdempotencyLevel) {
         size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) IdempotencyLevel);
       }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
@@ -5574,10 +6521,10 @@
       if (other == null) {
         return;
       }
-      if (other.Deprecated != false) {
+      if (other.HasDeprecated) {
         Deprecated = other.Deprecated;
       }
-      if (other.IdempotencyLevel != 0) {
+      if (other.HasIdempotencyLevel) {
         IdempotencyLevel = other.IdempotencyLevel;
       }
       uninterpretedOption_.Add(other.uninterpretedOption_);
@@ -5597,7 +6544,7 @@
             break;
           }
           case 272: {
-            idempotencyLevel_ = (global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) input.ReadEnum();
+            IdempotencyLevel = (global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) input.ReadEnum();
             break;
           }
           case 7994: {
@@ -5645,6 +6592,7 @@
   internal sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption> {
     private static readonly pb::MessageParser<UninterpretedOption> _parser = new pb::MessageParser<UninterpretedOption>(() => new UninterpretedOption());
     private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<UninterpretedOption> Parser { get { return _parser; } }
 
@@ -5667,6 +6615,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public UninterpretedOption(UninterpretedOption other) : this() {
+      _hasBits0 = other._hasBits0;
       name_ = other.name_.Clone();
       identifierValue_ = other.identifierValue_;
       positiveIntValue_ = other.positiveIntValue_;
@@ -5694,73 +6643,148 @@
 
     /// <summary>Field number for the "identifier_value" field.</summary>
     public const int IdentifierValueFieldNumber = 3;
-    private string identifierValue_ = "";
+    private readonly static string IdentifierValueDefaultValue = "";
+
+    private string identifierValue_;
     /// <summary>
     /// The value of the uninterpreted option, in whatever type the tokenizer
     /// identified it as during parsing. Exactly one of these should be set.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string IdentifierValue {
-      get { return identifierValue_; }
+      get { return identifierValue_ ?? IdentifierValueDefaultValue; }
       set {
         identifierValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "identifier_value" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasIdentifierValue {
+      get { return identifierValue_ != null; }
+    }
+    /// <summary>Clears the value of the "identifier_value" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearIdentifierValue() {
+      identifierValue_ = null;
+    }
 
     /// <summary>Field number for the "positive_int_value" field.</summary>
     public const int PositiveIntValueFieldNumber = 4;
+    private readonly static ulong PositiveIntValueDefaultValue = 0UL;
+
     private ulong positiveIntValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ulong PositiveIntValue {
-      get { return positiveIntValue_; }
+      get { if ((_hasBits0 & 1) != 0) { return positiveIntValue_; } else { return PositiveIntValueDefaultValue; } }
       set {
+        _hasBits0 |= 1;
         positiveIntValue_ = value;
       }
     }
+    /// <summary>Gets whether the "positive_int_value" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasPositiveIntValue {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "positive_int_value" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearPositiveIntValue() {
+      _hasBits0 &= ~1;
+    }
 
     /// <summary>Field number for the "negative_int_value" field.</summary>
     public const int NegativeIntValueFieldNumber = 5;
+    private readonly static long NegativeIntValueDefaultValue = 0L;
+
     private long negativeIntValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public long NegativeIntValue {
-      get { return negativeIntValue_; }
+      get { if ((_hasBits0 & 2) != 0) { return negativeIntValue_; } else { return NegativeIntValueDefaultValue; } }
       set {
+        _hasBits0 |= 2;
         negativeIntValue_ = value;
       }
     }
+    /// <summary>Gets whether the "negative_int_value" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasNegativeIntValue {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "negative_int_value" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearNegativeIntValue() {
+      _hasBits0 &= ~2;
+    }
 
     /// <summary>Field number for the "double_value" field.</summary>
     public const int DoubleValueFieldNumber = 6;
+    private readonly static double DoubleValueDefaultValue = 0D;
+
     private double doubleValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public double DoubleValue {
-      get { return doubleValue_; }
+      get { if ((_hasBits0 & 4) != 0) { return doubleValue_; } else { return DoubleValueDefaultValue; } }
       set {
+        _hasBits0 |= 4;
         doubleValue_ = value;
       }
     }
+    /// <summary>Gets whether the "double_value" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasDoubleValue {
+      get { return (_hasBits0 & 4) != 0; }
+    }
+    /// <summary>Clears the value of the "double_value" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearDoubleValue() {
+      _hasBits0 &= ~4;
+    }
 
     /// <summary>Field number for the "string_value" field.</summary>
     public const int StringValueFieldNumber = 7;
-    private pb::ByteString stringValue_ = pb::ByteString.Empty;
+    private readonly static pb::ByteString StringValueDefaultValue = pb::ByteString.Empty;
+
+    private pb::ByteString stringValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public pb::ByteString StringValue {
-      get { return stringValue_; }
+      get { return stringValue_ ?? StringValueDefaultValue; }
       set {
         stringValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "string_value" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasStringValue {
+      get { return stringValue_ != null; }
+    }
+    /// <summary>Clears the value of the "string_value" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearStringValue() {
+      stringValue_ = null;
+    }
 
     /// <summary>Field number for the "aggregate_value" field.</summary>
     public const int AggregateValueFieldNumber = 8;
-    private string aggregateValue_ = "";
+    private readonly static string AggregateValueDefaultValue = "";
+
+    private string aggregateValue_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string AggregateValue {
-      get { return aggregateValue_; }
+      get { return aggregateValue_ ?? AggregateValueDefaultValue; }
       set {
         aggregateValue_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
       }
     }
+    /// <summary>Gets whether the "aggregate_value" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool HasAggregateValue {
+      get { return aggregateValue_ != null; }
+    }
+    /// <summary>Clears the value of the "aggregate_value" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void ClearAggregateValue() {
+      aggregateValue_ = null;
+    }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
@@ -5789,12 +6813,12 @@
     public override int GetHashCode() {
       int hash = 1;
       hash ^= name_.GetHashCode();
-      if (IdentifierValue.Length != 0) hash ^= IdentifierValue.GetHashCode();
-      if (PositiveIntValue != 0UL) hash ^= PositiveIntValue.GetHashCode();
-      if (NegativeIntValue != 0L) hash ^= NegativeIntValue.GetHashCode();
-      if (DoubleValue != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleValue);
-      if (StringValue.Length != 0) hash ^= StringValue.GetHashCode();
-      if (AggregateValue.Length != 0) hash ^= AggregateValue.GetHashCode();
+      if (HasIdentifierValue) hash ^= IdentifierValue.GetHashCode();
+      if (HasPositiveIntValue) hash ^= PositiveIntValue.GetHashCode();
+      if (HasNegativeIntValue) hash ^= NegativeIntValue.GetHashCode();
+      if (HasDoubleValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleValue);
+      if (HasStringValue) hash ^= StringValue.GetHashCode();
+      if (HasAggregateValue) hash ^= AggregateValue.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -5809,27 +6833,27 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       name_.WriteTo(output, _repeated_name_codec);
-      if (IdentifierValue.Length != 0) {
+      if (HasIdentifierValue) {
         output.WriteRawTag(26);
         output.WriteString(IdentifierValue);
       }
-      if (PositiveIntValue != 0UL) {
+      if (HasPositiveIntValue) {
         output.WriteRawTag(32);
         output.WriteUInt64(PositiveIntValue);
       }
-      if (NegativeIntValue != 0L) {
+      if (HasNegativeIntValue) {
         output.WriteRawTag(40);
         output.WriteInt64(NegativeIntValue);
       }
-      if (DoubleValue != 0D) {
+      if (HasDoubleValue) {
         output.WriteRawTag(49);
         output.WriteDouble(DoubleValue);
       }
-      if (StringValue.Length != 0) {
+      if (HasStringValue) {
         output.WriteRawTag(58);
         output.WriteBytes(StringValue);
       }
-      if (AggregateValue.Length != 0) {
+      if (HasAggregateValue) {
         output.WriteRawTag(66);
         output.WriteString(AggregateValue);
       }
@@ -5842,22 +6866,22 @@
     public int CalculateSize() {
       int size = 0;
       size += name_.CalculateSize(_repeated_name_codec);
-      if (IdentifierValue.Length != 0) {
+      if (HasIdentifierValue) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(IdentifierValue);
       }
-      if (PositiveIntValue != 0UL) {
+      if (HasPositiveIntValue) {
         size += 1 + pb::CodedOutputStream.ComputeUInt64Size(PositiveIntValue);
       }
-      if (NegativeIntValue != 0L) {
+      if (HasNegativeIntValue) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(NegativeIntValue);
       }
-      if (DoubleValue != 0D) {
+      if (HasDoubleValue) {
         size += 1 + 8;
       }
-      if (StringValue.Length != 0) {
+      if (HasStringValue) {
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(StringValue);
       }
-      if (AggregateValue.Length != 0) {
+      if (HasAggregateValue) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(AggregateValue);
       }
       if (_unknownFields != null) {
@@ -5872,22 +6896,22 @@
         return;
       }
       name_.Add(other.name_);
-      if (other.IdentifierValue.Length != 0) {
+      if (other.HasIdentifierValue) {
         IdentifierValue = other.IdentifierValue;
       }
-      if (other.PositiveIntValue != 0UL) {
+      if (other.HasPositiveIntValue) {
         PositiveIntValue = other.PositiveIntValue;
       }
-      if (other.NegativeIntValue != 0L) {
+      if (other.HasNegativeIntValue) {
         NegativeIntValue = other.NegativeIntValue;
       }
-      if (other.DoubleValue != 0D) {
+      if (other.HasDoubleValue) {
         DoubleValue = other.DoubleValue;
       }
-      if (other.StringValue.Length != 0) {
+      if (other.HasStringValue) {
         StringValue = other.StringValue;
       }
-      if (other.AggregateValue.Length != 0) {
+      if (other.HasAggregateValue) {
         AggregateValue = other.AggregateValue;
       }
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -5947,6 +6971,7 @@
       internal sealed partial class NamePart : pb::IMessage<NamePart> {
         private static readonly pb::MessageParser<NamePart> _parser = new pb::MessageParser<NamePart>(() => new NamePart());
         private pb::UnknownFieldSet _unknownFields;
+        private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<NamePart> Parser { get { return _parser; } }
 
@@ -5969,6 +6994,7 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public NamePart(NamePart other) : this() {
+          _hasBits0 = other._hasBits0;
           namePart_ = other.namePart_;
           isExtension_ = other.isExtension_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@@ -5981,25 +7007,50 @@
 
         /// <summary>Field number for the "name_part" field.</summary>
         public const int NamePart_FieldNumber = 1;
-        private string namePart_ = "";
+        private readonly static string NamePart_DefaultValue = "";
+
+        private string namePart_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public string NamePart_ {
-          get { return namePart_; }
+          get { return namePart_ ?? NamePart_DefaultValue; }
           set {
             namePart_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
           }
         }
+        /// <summary>Gets whether the "name_part" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasNamePart_ {
+          get { return namePart_ != null; }
+        }
+        /// <summary>Clears the value of the "name_part" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearNamePart_() {
+          namePart_ = null;
+        }
 
         /// <summary>Field number for the "is_extension" field.</summary>
         public const int IsExtensionFieldNumber = 2;
+        private readonly static bool IsExtensionDefaultValue = false;
+
         private bool isExtension_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public bool IsExtension {
-          get { return isExtension_; }
+          get { if ((_hasBits0 & 1) != 0) { return isExtension_; } else { return IsExtensionDefaultValue; } }
           set {
+            _hasBits0 |= 1;
             isExtension_ = value;
           }
         }
+        /// <summary>Gets whether the "is_extension" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasIsExtension {
+          get { return (_hasBits0 & 1) != 0; }
+        }
+        /// <summary>Clears the value of the "is_extension" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearIsExtension() {
+          _hasBits0 &= ~1;
+        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override bool Equals(object other) {
@@ -6022,8 +7073,8 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override int GetHashCode() {
           int hash = 1;
-          if (NamePart_.Length != 0) hash ^= NamePart_.GetHashCode();
-          if (IsExtension != false) hash ^= IsExtension.GetHashCode();
+          if (HasNamePart_) hash ^= NamePart_.GetHashCode();
+          if (HasIsExtension) hash ^= IsExtension.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -6037,11 +7088,11 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public void WriteTo(pb::CodedOutputStream output) {
-          if (NamePart_.Length != 0) {
+          if (HasNamePart_) {
             output.WriteRawTag(10);
             output.WriteString(NamePart_);
           }
-          if (IsExtension != false) {
+          if (HasIsExtension) {
             output.WriteRawTag(16);
             output.WriteBool(IsExtension);
           }
@@ -6053,10 +7104,10 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int CalculateSize() {
           int size = 0;
-          if (NamePart_.Length != 0) {
+          if (HasNamePart_) {
             size += 1 + pb::CodedOutputStream.ComputeStringSize(NamePart_);
           }
-          if (IsExtension != false) {
+          if (HasIsExtension) {
             size += 1 + 1;
           }
           if (_unknownFields != null) {
@@ -6070,10 +7121,10 @@
           if (other == null) {
             return;
           }
-          if (other.NamePart_.Length != 0) {
+          if (other.HasNamePart_) {
             NamePart_ = other.NamePart_;
           }
-          if (other.IsExtension != false) {
+          if (other.HasIsExtension) {
             IsExtension = other.IsExtension;
           }
           _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@@ -6370,7 +7421,9 @@
 
         /// <summary>Field number for the "leading_comments" field.</summary>
         public const int LeadingCommentsFieldNumber = 3;
-        private string leadingComments_ = "";
+        private readonly static string LeadingCommentsDefaultValue = "";
+
+        private string leadingComments_;
         /// <summary>
         /// If this SourceCodeInfo represents a complete declaration, these are any
         /// comments appearing before and after the declaration which appear to be
@@ -6422,22 +7475,44 @@
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public string LeadingComments {
-          get { return leadingComments_; }
+          get { return leadingComments_ ?? LeadingCommentsDefaultValue; }
           set {
             leadingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
           }
         }
+        /// <summary>Gets whether the "leading_comments" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasLeadingComments {
+          get { return leadingComments_ != null; }
+        }
+        /// <summary>Clears the value of the "leading_comments" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearLeadingComments() {
+          leadingComments_ = null;
+        }
 
         /// <summary>Field number for the "trailing_comments" field.</summary>
         public const int TrailingCommentsFieldNumber = 4;
-        private string trailingComments_ = "";
+        private readonly static string TrailingCommentsDefaultValue = "";
+
+        private string trailingComments_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public string TrailingComments {
-          get { return trailingComments_; }
+          get { return trailingComments_ ?? TrailingCommentsDefaultValue; }
           set {
             trailingComments_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
           }
         }
+        /// <summary>Gets whether the "trailing_comments" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasTrailingComments {
+          get { return trailingComments_ != null; }
+        }
+        /// <summary>Clears the value of the "trailing_comments" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearTrailingComments() {
+          trailingComments_ = null;
+        }
 
         /// <summary>Field number for the "leading_detached_comments" field.</summary>
         public const int LeadingDetachedCommentsFieldNumber = 6;
@@ -6475,8 +7550,8 @@
           int hash = 1;
           hash ^= path_.GetHashCode();
           hash ^= span_.GetHashCode();
-          if (LeadingComments.Length != 0) hash ^= LeadingComments.GetHashCode();
-          if (TrailingComments.Length != 0) hash ^= TrailingComments.GetHashCode();
+          if (HasLeadingComments) hash ^= LeadingComments.GetHashCode();
+          if (HasTrailingComments) hash ^= TrailingComments.GetHashCode();
           hash ^= leadingDetachedComments_.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
@@ -6493,11 +7568,11 @@
         public void WriteTo(pb::CodedOutputStream output) {
           path_.WriteTo(output, _repeated_path_codec);
           span_.WriteTo(output, _repeated_span_codec);
-          if (LeadingComments.Length != 0) {
+          if (HasLeadingComments) {
             output.WriteRawTag(26);
             output.WriteString(LeadingComments);
           }
-          if (TrailingComments.Length != 0) {
+          if (HasTrailingComments) {
             output.WriteRawTag(34);
             output.WriteString(TrailingComments);
           }
@@ -6512,10 +7587,10 @@
           int size = 0;
           size += path_.CalculateSize(_repeated_path_codec);
           size += span_.CalculateSize(_repeated_span_codec);
-          if (LeadingComments.Length != 0) {
+          if (HasLeadingComments) {
             size += 1 + pb::CodedOutputStream.ComputeStringSize(LeadingComments);
           }
-          if (TrailingComments.Length != 0) {
+          if (HasTrailingComments) {
             size += 1 + pb::CodedOutputStream.ComputeStringSize(TrailingComments);
           }
           size += leadingDetachedComments_.CalculateSize(_repeated_leadingDetachedComments_codec);
@@ -6532,10 +7607,10 @@
           }
           path_.Add(other.path_);
           span_.Add(other.span_);
-          if (other.LeadingComments.Length != 0) {
+          if (other.HasLeadingComments) {
             LeadingComments = other.LeadingComments;
           }
-          if (other.TrailingComments.Length != 0) {
+          if (other.HasTrailingComments) {
             TrailingComments = other.TrailingComments;
           }
           leadingDetachedComments_.Add(other.leadingDetachedComments_);
@@ -6718,6 +7793,7 @@
       internal sealed partial class Annotation : pb::IMessage<Annotation> {
         private static readonly pb::MessageParser<Annotation> _parser = new pb::MessageParser<Annotation>(() => new Annotation());
         private pb::UnknownFieldSet _unknownFields;
+        private int _hasBits0;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pb::MessageParser<Annotation> Parser { get { return _parser; } }
 
@@ -6740,6 +7816,7 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public Annotation(Annotation other) : this() {
+          _hasBits0 = other._hasBits0;
           path_ = other.path_.Clone();
           sourceFile_ = other.sourceFile_;
           begin_ = other.begin_;
@@ -6768,20 +7845,34 @@
 
         /// <summary>Field number for the "source_file" field.</summary>
         public const int SourceFileFieldNumber = 2;
-        private string sourceFile_ = "";
+        private readonly static string SourceFileDefaultValue = "";
+
+        private string sourceFile_;
         /// <summary>
         /// Identifies the filesystem path to the original source .proto.
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public string SourceFile {
-          get { return sourceFile_; }
+          get { return sourceFile_ ?? SourceFileDefaultValue; }
           set {
             sourceFile_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
           }
         }
+        /// <summary>Gets whether the "source_file" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasSourceFile {
+          get { return sourceFile_ != null; }
+        }
+        /// <summary>Clears the value of the "source_file" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearSourceFile() {
+          sourceFile_ = null;
+        }
 
         /// <summary>Field number for the "begin" field.</summary>
         public const int BeginFieldNumber = 3;
+        private readonly static int BeginDefaultValue = 0;
+
         private int begin_;
         /// <summary>
         /// Identifies the starting offset in bytes in the generated code
@@ -6789,14 +7880,27 @@
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int Begin {
-          get { return begin_; }
+          get { if ((_hasBits0 & 1) != 0) { return begin_; } else { return BeginDefaultValue; } }
           set {
+            _hasBits0 |= 1;
             begin_ = value;
           }
         }
+        /// <summary>Gets whether the "begin" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasBegin {
+          get { return (_hasBits0 & 1) != 0; }
+        }
+        /// <summary>Clears the value of the "begin" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearBegin() {
+          _hasBits0 &= ~1;
+        }
 
         /// <summary>Field number for the "end" field.</summary>
         public const int EndFieldNumber = 4;
+        private readonly static int EndDefaultValue = 0;
+
         private int end_;
         /// <summary>
         /// Identifies the ending offset in bytes in the generated code that
@@ -6805,11 +7909,22 @@
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public int End {
-          get { return end_; }
+          get { if ((_hasBits0 & 2) != 0) { return end_; } else { return EndDefaultValue; } }
           set {
+            _hasBits0 |= 2;
             end_ = value;
           }
         }
+        /// <summary>Gets whether the "end" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public bool HasEnd {
+          get { return (_hasBits0 & 2) != 0; }
+        }
+        /// <summary>Clears the value of the "end" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public void ClearEnd() {
+          _hasBits0 &= ~2;
+        }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override bool Equals(object other) {
@@ -6835,9 +7950,9 @@
         public override int GetHashCode() {
           int hash = 1;
           hash ^= path_.GetHashCode();
-          if (SourceFile.Length != 0) hash ^= SourceFile.GetHashCode();
-          if (Begin != 0) hash ^= Begin.GetHashCode();
-          if (End != 0) hash ^= End.GetHashCode();
+          if (HasSourceFile) hash ^= SourceFile.GetHashCode();
+          if (HasBegin) hash ^= Begin.GetHashCode();
+          if (HasEnd) hash ^= End.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -6852,15 +7967,15 @@
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public void WriteTo(pb::CodedOutputStream output) {
           path_.WriteTo(output, _repeated_path_codec);
-          if (SourceFile.Length != 0) {
+          if (HasSourceFile) {
             output.WriteRawTag(18);
             output.WriteString(SourceFile);
           }
-          if (Begin != 0) {
+          if (HasBegin) {
             output.WriteRawTag(24);
             output.WriteInt32(Begin);
           }
-          if (End != 0) {
+          if (HasEnd) {
             output.WriteRawTag(32);
             output.WriteInt32(End);
           }
@@ -6873,13 +7988,13 @@
         public int CalculateSize() {
           int size = 0;
           size += path_.CalculateSize(_repeated_path_codec);
-          if (SourceFile.Length != 0) {
+          if (HasSourceFile) {
             size += 1 + pb::CodedOutputStream.ComputeStringSize(SourceFile);
           }
-          if (Begin != 0) {
+          if (HasBegin) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(Begin);
           }
-          if (End != 0) {
+          if (HasEnd) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
           }
           if (_unknownFields != null) {
@@ -6894,13 +8009,13 @@
             return;
           }
           path_.Add(other.path_);
-          if (other.SourceFile.Length != 0) {
+          if (other.HasSourceFile) {
             SourceFile = other.SourceFile;
           }
-          if (other.Begin != 0) {
+          if (other.HasBegin) {
             Begin = other.Begin;
           }
-          if (other.End != 0) {
+          if (other.HasEnd) {
             End = other.End;
           }
           _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
diff --git a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
index 82ce505..85b7d39 100644
--- a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
@@ -57,6 +57,7 @@
             return getValueDelegate(message);
         }
 
+        public abstract bool HasValue(IMessage message);
         public abstract void Clear(IMessage message);
         public abstract void SetValue(IMessage message, object value);
     }
diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
index 152467d..0a46f9e 100644
--- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
@@ -79,8 +79,7 @@
                 throw new DescriptorValidationException(this, "Field numbers must be positive integers.");
             }
             ContainingType = parent;
-            // OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction.
-            if (proto.OneofIndex != -1)
+            if (proto.HasOneofIndex)
             {
                 if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count)
                 {
@@ -184,6 +183,11 @@
         /// </summary>
         public bool IsRepeated => Proto.Label == FieldDescriptorProto.Types.Label.Repeated;
 
+        /// <summary>

+        /// Returns <c>true</c> if this field is a required field; <c>false</c> otherwise.

+        /// </summary>
+        public bool IsRequired => Proto.Label == FieldDescriptorProto.Types.Label.Required;
+
         /// <summary>
         /// Returns <c>true</c> if this field is a map field; <c>false</c> otherwise.
         /// </summary>
@@ -192,13 +196,8 @@
         /// <summary>
         /// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
         /// </summary>
-        public bool IsPacked => 
-            // Note the || rather than && here - we're effectively defaulting to packed, because that *is*
-            // the default in proto3, which is all we support. We may give the wrong result for the protos
-            // within descriptor.proto, but that's okay, as they're never exposed and we don't use IsPacked
-            // within the runtime.
-            Proto.Options == null || Proto.Options.Packed;
-        
+        public bool IsPacked => File.Proto.Syntax == "proto2" ? Proto.Options?.Packed ?? false : !Proto.Options.HasPacked || Proto.Options.Packed;

+

         /// <summary>
         /// Returns the type of the field.
         /// </summary>
@@ -247,9 +246,9 @@
         {
             get
             {
-                if (fieldType != FieldType.Message)
+                if (fieldType != FieldType.Message && fieldType != FieldType.Group)
                 {
-                    throw new InvalidOperationException("MessageType is only valid for message fields.");
+                    throw new InvalidOperationException("MessageType is only valid for message or group fields.");
                 }
                 return messageType;
             }
@@ -265,12 +264,12 @@
         /// </summary>
         internal void CrossLink()
         {
-            if (Proto.TypeName != "")
+            if (Proto.HasTypeName)
             {
                 IDescriptor typeDescriptor =
                     File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
 
-                if (Proto.Type != 0)
+                if (Proto.HasType)
                 {
                     // Choose field type based on symbol.
                     if (typeDescriptor is MessageDescriptor)
@@ -287,7 +286,7 @@
                     }
                 }
 
-                if (fieldType == FieldType.Message)
+                if (fieldType == FieldType.Message || fieldType == FieldType.Group)
                 {
                     if (!(typeDescriptor is MessageDescriptor))
                     {
@@ -295,7 +294,7 @@
                     }
                     messageType = (MessageDescriptor) typeDescriptor;
 
-                    if (Proto.DefaultValue != "")
+                    if (Proto.HasDefaultValue)
                     {
                         throw new DescriptorValidationException(this, "Messages can't have default values.");
                     }
@@ -325,7 +324,7 @@
 
             File.DescriptorPool.AddFieldByNumber(this);
 
-            if (ContainingType != null && ContainingType.Proto.Options != null && ContainingType.Proto.Options.MessageSetWireFormat)
+            if (ContainingType != null && ContainingType.Proto.HasOptions && ContainingType.Proto.Options.MessageSetWireFormat)
             {
                 throw new DescriptorValidationException(this, "MessageSet format is not supported.");
             }
diff --git a/csharp/src/Google.Protobuf/Reflection/FieldType.cs b/csharp/src/Google.Protobuf/Reflection/FieldType.cs
index 1658e34..37af179 100644
--- a/csharp/src/Google.Protobuf/Reflection/FieldType.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FieldType.cs
@@ -74,7 +74,7 @@
         /// </summary>
         String,
         /// <summary>
-        /// The field type used for groups (not supported in this implementation).
+        /// The field type used for groups.
         /// </summary>
         Group,
         /// <summary>
diff --git a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
index cfe56fd..8f7ef3c 100644
--- a/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
@@ -52,6 +52,11 @@
         void Clear(IMessage message);
 
         /// <summary>
+        /// Indicates whether the field in the specified message is set. For proto3 fields, this throws an <see cref="InvalidOperationException"/>
+        /// </summary>
+        bool HasValue(IMessage message);
+
+        /// <summary>
         /// Fetches the field value. For repeated values, this will be an
         /// <see cref="IList"/> implementation. For map values, this will be an
         /// <see cref="IDictionary"/> implementation.
diff --git a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs
index 9ed7f8c..56e3ddd 100644
--- a/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs
@@ -51,6 +51,11 @@
             list.Clear();
         }
 
+        public override bool HasValue(IMessage message)
+        {
+            throw new InvalidOperationException("HasValue is not implemented for map fields");
+        }
+
         public override void SetValue(IMessage message, object value)
         {
             throw new InvalidOperationException("SetValue is not implemented for map fields");
diff --git a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs b/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
deleted file mode 100644
index 8c055d6..0000000
--- a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-#region Copyright notice and license

-// Protocol Buffers - Google's data interchange format

-// Copyright 2008 Google Inc.  All rights reserved.

-// https://developers.google.com/protocol-buffers/

-//

-// Redistribution and use in source and binary forms, with or without

-// modification, are permitted provided that the following conditions are

-// met:

-//

-//     * Redistributions of source code must retain the above copyright

-// notice, this list of conditions and the following disclaimer.

-//     * Redistributions in binary form must reproduce the above

-// copyright notice, this list of conditions and the following disclaimer

-// in the documentation and/or other materials provided with the

-// distribution.

-//     * Neither the name of Google Inc. nor the names of its

-// contributors may be used to endorse or promote products derived from

-// this software without specific prior written permission.

-//

-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-#endregion

-

-// This file just contains partial classes for any autogenerated classes that need additional support.

-namespace Google.Protobuf.Reflection

-{

-    internal partial class FieldDescriptorProto

-    {

-        // We can't tell the difference between "explicitly set to 0" and "not set"

-        // in proto3, but we need to tell the difference for OneofIndex. descriptor.proto

-        // is really a proto2 file, but the runtime doesn't know about proto2 semantics...

-        // We fake it by defaulting to -1.

-        partial void OnConstruction()

-        {

-            OneofIndex = -1;

-        }

-    }

-

-    internal partial class FieldOptions

-    {

-        // We can't tell the difference between "explicitly set to false" and "not set"

-        // in proto3, but we need to tell the difference for FieldDescriptor.IsPacked.

-        // This won't work if we ever need to support proto2, but at that point we'll be

-        // able to remove this hack and use field presence instead. 

-        partial void OnConstruction()

-        {

-            Packed = true;

-        }

-    }

-}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
index feaeba0..b22e8d1 100644
--- a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
+++ b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
@@ -112,6 +112,9 @@
         internal static Action<IMessage> CreateActionIMessage(MethodInfo method) =>
             GetReflectionHelper(method.DeclaringType, typeof(object)).CreateActionIMessage(method);
 
+        internal static Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method) =>
+            GetReflectionHelper(method.DeclaringType, method.ReturnType).CreateFuncIMessageBool(method);
+
         /// <summary>
         /// Creates a reflection helper for the given type arguments. Currently these are created on demand
         /// rather than cached; this will be "busy" when initially loading a message's descriptor, but after that
@@ -129,6 +132,7 @@
             Action<IMessage> CreateActionIMessage(MethodInfo method);
             Func<IMessage, object> CreateFuncIMessageObject(MethodInfo method);
             Action<IMessage, object> CreateActionIMessageObject(MethodInfo method);
+            Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method);
         }
 
         private class ReflectionHelper<T1, T2> : IReflectionHelper
@@ -170,6 +174,12 @@
                 var del = (Action<T1, T2>) method.CreateDelegate(typeof(Action<T1, T2>));
                 return (message, arg) => del((T1) message, (T2) arg);
             }
+
+            public Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method)
+            {
+                var del = (Func<T1, bool>)method.CreateDelegate(typeof(Func<T1, bool>));
+                return message => del((T1)message);
+            }
         }
 
         // Runtime compatibility checking code - see ReflectionHelper<T1, T2>.CreateFuncIMessageInt32 for
diff --git a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
index bd40847..afb4a69 100644
--- a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
@@ -51,6 +51,11 @@
             list.Clear();
         }
 
+        public override bool HasValue(IMessage message)
+        {
+            throw new InvalidOperationException("HasValue is not implemented for repeated fields");
+        }
+
         public override void SetValue(IMessage message, object value)
         {
             throw new InvalidOperationException("SetValue is not implemented for repeated fields");
diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
index bbac217..d541570 100644
--- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
@@ -48,6 +48,7 @@
 
         private readonly Action<IMessage, object> setValueDelegate;
         private readonly Action<IMessage> clearDelegate;
+        private readonly Func<IMessage, bool> hasDelegate;
 
         internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor)
         {
@@ -56,16 +57,25 @@
                 throw new ArgumentException("Not all required properties/methods available");
             }
             setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
+            if (descriptor.File.Proto.Syntax == "proto2")
+            {
+                MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
+                hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
+                MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
+                clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod ?? throw new ArgumentException("Not all required properties/methods are available"));
+            }
+            else
+            {
+                hasDelegate = (_) => throw new InvalidOperationException("HasValue is not implemented for proto3 fields"); var clrType = property.PropertyType;
 
-            var clrType = property.PropertyType;
-            
-            // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
-            object defaultValue =
-                descriptor.FieldType == FieldType.Message ? null
-                : clrType == typeof(string) ? ""
-                : clrType == typeof(ByteString) ? ByteString.Empty
-                : Activator.CreateInstance(clrType);
-            clearDelegate = message => SetValue(message, defaultValue);
+                // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) 
+                object defaultValue =
+                    descriptor.FieldType == FieldType.Message ? null
+                    : clrType == typeof(string) ? ""
+                    : clrType == typeof(ByteString) ? ByteString.Empty
+                    : Activator.CreateInstance(clrType);
+                clearDelegate = message => SetValue(message, defaultValue);
+            }
         }
 
         public override void Clear(IMessage message)
@@ -73,6 +83,11 @@
             clearDelegate(message);
         }
 
+        public override bool HasValue(IMessage message)
+        {
+            return hasDelegate(message);
+        }
+
         public override void SetValue(IMessage message, object value)
         {
             setValueDelegate(message, value);
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
index e4a4a36..438e1db 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
@@ -328,7 +328,7 @@
       }
       if (other.sourceContext_ != null) {
         if (sourceContext_ == null) {
-          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+          SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
         }
         SourceContext.MergeFrom(other.SourceContext);
       }
@@ -365,9 +365,9 @@
           }
           case 42: {
             if (sourceContext_ == null) {
-              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+              SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
             }
-            input.ReadMessage(sourceContext_);
+            input.ReadMessage(SourceContext);
             break;
           }
           case 50: {
@@ -375,7 +375,7 @@
             break;
           }
           case 56: {
-            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
             break;
           }
         }
@@ -688,7 +688,7 @@
             break;
           }
           case 56: {
-            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
             break;
           }
         }
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
index 3e2fe54..52bd343 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
@@ -312,7 +312,7 @@
       options_.Add(other.options_);
       if (other.sourceContext_ != null) {
         if (sourceContext_ == null) {
-          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+          SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
         }
         SourceContext.MergeFrom(other.SourceContext);
       }
@@ -348,13 +348,13 @@
           }
           case 42: {
             if (sourceContext_ == null) {
-              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+              SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
             }
-            input.ReadMessage(sourceContext_);
+            input.ReadMessage(SourceContext);
             break;
           }
           case 48: {
-            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
             break;
           }
         }
@@ -726,11 +726,11 @@
             _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
-            kind_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
+            Kind = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum();
             break;
           }
           case 16: {
-            cardinality_ = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum();
+            Cardinality = (global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality) input.ReadEnum();
             break;
           }
           case 24: {
@@ -1084,7 +1084,7 @@
       options_.Add(other.options_);
       if (other.sourceContext_ != null) {
         if (sourceContext_ == null) {
-          sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+          SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
         }
         SourceContext.MergeFrom(other.SourceContext);
       }
@@ -1116,13 +1116,13 @@
           }
           case 34: {
             if (sourceContext_ == null) {
-              sourceContext_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+              SourceContext = new global::Google.Protobuf.WellKnownTypes.SourceContext();
             }
-            input.ReadMessage(sourceContext_);
+            input.ReadMessage(SourceContext);
             break;
           }
           case 40: {
-            syntax_ = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
+            Syntax = (global::Google.Protobuf.WellKnownTypes.Syntax) input.ReadEnum();
             break;
           }
         }
@@ -1467,7 +1467,7 @@
       }
       if (other.value_ != null) {
         if (value_ == null) {
-          value_ = new global::Google.Protobuf.WellKnownTypes.Any();
+          Value = new global::Google.Protobuf.WellKnownTypes.Any();
         }
         Value.MergeFrom(other.Value);
       }
@@ -1488,9 +1488,9 @@
           }
           case 18: {
             if (value_ == null) {
-              value_ = new global::Google.Protobuf.WellKnownTypes.Any();
+              Value = new global::Google.Protobuf.WellKnownTypes.Any();
             }
-            input.ReadMessage(value_);
+            input.ReadMessage(Value);
             break;
           }
         }
diff --git a/csharp/src/Google.Protobuf/WireFormat.cs b/csharp/src/Google.Protobuf/WireFormat.cs
index faf1e71..f3adeb1 100644
--- a/csharp/src/Google.Protobuf/WireFormat.cs
+++ b/csharp/src/Google.Protobuf/WireFormat.cs
@@ -61,11 +61,11 @@
             /// </summary>

             LengthDelimited = 2,

             /// <summary>

-            /// A "start group" value - not supported by this implementation.

+            /// A "start group" value

             /// </summary>

             StartGroup = 3,

             /// <summary>

-            /// An "end group" value - not supported by this implementation.

+            /// An "end group" value

             /// </summary>

             EndGroup = 4,

             /// <summary>

diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
index 9ceffa8..df59961 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -47,8 +47,8 @@
 namespace csharp {
 
 EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal, const Options *options)
-    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
+                                       int presenceIndex, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
 }
 
 EnumFieldGenerator::~EnumFieldGenerator() {
@@ -56,7 +56,7 @@
 
 void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) {
   printer->Print(variables_,
-    "$name$_ = ($type_name$) input.ReadEnum();\n");
+    "$property_name$ = ($type_name$) input.ReadEnum();\n");
 }
 
 void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
@@ -82,8 +82,8 @@
 }
 
 EnumOneofFieldGenerator::EnumOneofFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
-  : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) {
+    const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+  : PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) {
 }
 
 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
index 631632b..bfb9bc8 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -44,7 +44,7 @@
 class EnumFieldGenerator : public PrimitiveFieldGenerator {
  public:
   EnumFieldGenerator(const FieldDescriptor* descriptor,
-                     int fieldOrdinal,
+                     int presenceIndex,
                      const Options *options);
   ~EnumFieldGenerator();
 
@@ -60,7 +60,7 @@
 class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator {
  public:
   EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
-                          int fieldOrdinal,
+                          int presenceIndex,
                           const Options *options);
   ~EnumOneofFieldGenerator();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 7e737e4..f880826 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -57,6 +57,9 @@
   // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
   // never effects the tag size.
   int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
+  if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+    tag_size /= 2;
+  }
   uint tag = internal::WireFormat::MakeTag(descriptor_);
   uint8 tag_array[5];
   io::CodedOutputStream::WriteTagToArray(tag, tag_array);
@@ -75,34 +78,52 @@
   (*variables)["name"] = name();
   (*variables)["descriptor_name"] = descriptor_->name();
   (*variables)["default_value"] = default_value();
-  if (has_default_value()) {
+  (*variables)["capitalized_type_name"] = capitalized_type_name();
+  (*variables)["number"] = number();
+  if (has_default_value() && !IsProto2(descriptor_->file())) {
     (*variables)["name_def_message"] =
       (*variables)["name"] + "_ = " + (*variables)["default_value"];
   } else {
     (*variables)["name_def_message"] = (*variables)["name"] + "_";
   }
-  (*variables)["capitalized_type_name"] = capitalized_type_name();
-  (*variables)["number"] = number();
-  (*variables)["has_property_check"] =
-    (*variables)["property_name"] + " != " + (*variables)["default_value"];
-  (*variables)["other_has_property_check"] = "other." +
-    (*variables)["property_name"] + " != " + (*variables)["default_value"];
+  if (IsProto2(descriptor_->file())) {
+    (*variables)["has_property_check"] = "Has" + (*variables)["property_name"];
+    (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"];
+    (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"];
+    (*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"];
+    if (presenceIndex_ != -1) {
+      string hasBitsNumber = SimpleItoa(presenceIndex_ / 32);
+      string hasBitsMask = SimpleItoa(1 << (presenceIndex_ % 32));
+      (*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0";
+      (*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask;
+      (*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask;
+    }
+  } else {
+    (*variables)["has_property_check"] =
+      (*variables)["property_name"] + " != " + (*variables)["default_value"];
+    (*variables)["other_has_property_check"] = "other." +
+      (*variables)["property_name"] + " != " + (*variables)["default_value"];
+  }
 }
 
 void FieldGeneratorBase::SetCommonOneofFieldVariables(
     std::map<string, string>* variables) {
   (*variables)["oneof_name"] = oneof_name();
-  (*variables)["has_property_check"] =
-    oneof_name() + "Case_ == " + oneof_property_name() +
-    "OneofCase." + property_name();
+  if (IsProto2(descriptor_->file())) {
+    (*variables)["has_property_check"] = "Has" + property_name();
+  } else {
+    (*variables)["has_property_check"] =
+      oneof_name() + "Case_ == " + oneof_property_name() +
+      "OneofCase." + property_name();
+  }
   (*variables)["oneof_property_name"] = oneof_property_name();
 }
 
 FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal, const Options* options)
+                                       int presenceIndex, const Options* options)
     : SourceGeneratorBase(descriptor->file(), options),
       descriptor_(descriptor),
-      fieldOrdinal_(fieldOrdinal) {
+      presenceIndex_(presenceIndex) {
   SetCommonFieldVariables(&variables_);
 }
 
@@ -251,36 +272,6 @@
   }
 }
 
-bool FieldGeneratorBase::is_nullable_type() {
-  switch (descriptor_->type()) {
-    case FieldDescriptor::TYPE_ENUM:
-    case FieldDescriptor::TYPE_DOUBLE:
-    case FieldDescriptor::TYPE_FLOAT:
-    case FieldDescriptor::TYPE_INT64:
-    case FieldDescriptor::TYPE_UINT64:
-    case FieldDescriptor::TYPE_INT32:
-    case FieldDescriptor::TYPE_FIXED64:
-    case FieldDescriptor::TYPE_FIXED32:
-    case FieldDescriptor::TYPE_BOOL:
-    case FieldDescriptor::TYPE_UINT32:
-    case FieldDescriptor::TYPE_SFIXED32:
-    case FieldDescriptor::TYPE_SFIXED64:
-    case FieldDescriptor::TYPE_SINT32:
-    case FieldDescriptor::TYPE_SINT64:
-      return false;
-
-    case FieldDescriptor::TYPE_MESSAGE:
-    case FieldDescriptor::TYPE_GROUP:
-    case FieldDescriptor::TYPE_STRING:
-    case FieldDescriptor::TYPE_BYTES:
-      return true;
-
-    default:
-      GOOGLE_LOG(FATAL)<< "Unknown field type.";
-      return true;
-  }
-}
-
 bool AllPrintableAscii(const std::string& text) {
   for(int i = 0; i < text.size(); i++) {
     if (text[i] < 0x20 || text[i] > 0x7e) {
@@ -290,14 +281,18 @@
   return true;
 }
 
-std::string FieldGeneratorBase::GetStringDefaultValueInternal() {
-  // No other default values needed for proto3...
-  return "\"\"";
+std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) {
+    if (descriptor->default_value_string().empty())
+        return "\"\"";
+    else
+        return "global::System.Encoding.UTF8.GetString(global::System.Convert.FromBase64String(\" +" + StringToBase64(descriptor->default_value_string()) + " +\"))";
 }
 
-std::string FieldGeneratorBase::GetBytesDefaultValueInternal() {
-  // No other default values needed for proto3...
-  return "pb::ByteString.Empty";
+std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
+    if (descriptor->default_value_string().empty())
+        return "pb::ByteString.Empty";
+    else
+        return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")";
 }
 
 std::string FieldGeneratorBase::default_value() {
@@ -307,9 +302,13 @@
 std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) {
   switch (descriptor->type()) {
     case FieldDescriptor::TYPE_ENUM:
-      // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to
-      // any C# enum. This means we don't need to work out what we actually mapped the enum value name to.
-     return "0";
+      if (IsProto2(descriptor_->file())) {
+        return GetClassName(descriptor->default_value_enum()->type()) + "." + 
+          GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name());
+      }
+      else {
+        return "0";
+      }
     case FieldDescriptor::TYPE_MESSAGE:
     case FieldDescriptor::TYPE_GROUP:
       if (IsWrapperType(descriptor)) {
@@ -357,9 +356,9 @@
         return "false";
       }
     case FieldDescriptor::TYPE_STRING:
-      return GetStringDefaultValueInternal();
+      return GetStringDefaultValueInternal(descriptor);
     case FieldDescriptor::TYPE_BYTES:
-      return GetBytesDefaultValueInternal();
+      return GetBytesDefaultValueInternal(descriptor);
     case FieldDescriptor::TYPE_UINT32:
       return SimpleItoa(descriptor->default_value_uint32());
     case FieldDescriptor::TYPE_SFIXED32:
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index 62c2551..7eee6bf 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -47,7 +47,7 @@
 class FieldGeneratorBase : public SourceGeneratorBase {
  public:
   FieldGeneratorBase(const FieldDescriptor* descriptor,
-                     int fieldOrdinal,
+                     int presenceIndex,
                      const Options* options);
   ~FieldGeneratorBase();
 
@@ -67,7 +67,7 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  const int fieldOrdinal_;
+  const int presenceIndex_;
   std::map<string, string> variables_;
 
   void AddDeprecatedFlag(io::Printer* printer);
@@ -84,7 +84,6 @@
   std::string type_name();
   std::string type_name(const FieldDescriptor* descriptor);
   bool has_default_value();
-  bool is_nullable_type();
   std::string default_value();
   std::string default_value(const FieldDescriptor* descriptor);
   std::string number();
@@ -92,8 +91,8 @@
 
  private:
   void SetCommonFieldVariables(std::map<string, string>* variables);
-  std::string GetStringDefaultValueInternal();
-  std::string GetBytesDefaultValueInternal();
+  std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor);
+  std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase);
 };
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
index 0c93fc2..c0597fe 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -65,11 +65,11 @@
   std::vector<std::pair<string, string> > options;
   ParseGeneratorParameter(parameter, &options);
 
-  // We only support proto3 - but we make an exception for descriptor.proto.
+  // We only support proto3 - but we make an exception for descriptor.proto. 
   if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
-    *error = "C# code generation only supports proto3 syntax";
+    *error = "C# code generation only supports proto3 syntax"; 
     return false;
-  }
+  } 
 
   struct Options cli_options;
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index 04b6107..dace410 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -36,6 +36,7 @@
 #include <google/protobuf/stubs/hash.h>
 #include <limits>
 #include <vector>
+#include <sstream>
 
 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
 #include <google/protobuf/compiler/csharp/csharp_names.h>
@@ -452,55 +453,89 @@
 }
 
 FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
-                                         int fieldOrdinal,
+                                         int presenceIndex,
                                          const Options* options) {
   switch (descriptor->type()) {
     case FieldDescriptor::TYPE_GROUP:
     case FieldDescriptor::TYPE_MESSAGE:
       if (descriptor->is_repeated()) {
         if (descriptor->is_map()) {
-          return new MapFieldGenerator(descriptor, fieldOrdinal, options);
+          return new MapFieldGenerator(descriptor, presenceIndex, options);
         } else {
-          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options);
+          return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options);
         }
       } else {
         if (IsWrapperType(descriptor)) {
           if (descriptor->containing_oneof()) {
-            return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options);
+            return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options);
           } else {
-            return new WrapperFieldGenerator(descriptor, fieldOrdinal, options);
+            return new WrapperFieldGenerator(descriptor, presenceIndex, options);
           }
         } else {
           if (descriptor->containing_oneof()) {
-            return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options);
+            return new MessageOneofFieldGenerator(descriptor, presenceIndex, options);
           } else {
-            return new MessageFieldGenerator(descriptor, fieldOrdinal, options);
+            return new MessageFieldGenerator(descriptor, presenceIndex, options);
           }
         }
       }
     case FieldDescriptor::TYPE_ENUM:
       if (descriptor->is_repeated()) {
-        return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options);
+        return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options);
       } else {
         if (descriptor->containing_oneof()) {
-          return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options);
+          return new EnumOneofFieldGenerator(descriptor, presenceIndex, options);
         } else {
-          return new EnumFieldGenerator(descriptor, fieldOrdinal, options);
+          return new EnumFieldGenerator(descriptor, presenceIndex, options);
         }
       }
     default:
       if (descriptor->is_repeated()) {
-        return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
+        return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options);
       } else {
         if (descriptor->containing_oneof()) {
-          return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options);
+          return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options);
         } else {
-          return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options);
+          return new PrimitiveFieldGenerator(descriptor, presenceIndex, options);
         }
       }
   }
 }
 
+bool IsNullable(const FieldDescriptor* descriptor) {
+  if (descriptor->is_repeated()) {
+    return true;
+  }
+
+  switch (descriptor->type()) {
+    case FieldDescriptor::TYPE_ENUM:
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_BOOL:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_SINT64:
+      return false;
+
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      return true;
+
+    default:
+      GOOGLE_LOG(FATAL) << "Unknown field type.";
+      return true;
+  }
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index ec0b1c7..5b9f90e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -107,9 +107,11 @@
 std::string FileDescriptorToBase64(const FileDescriptor* descriptor);
 
 FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
-                                         int fieldOrdinal,
+                                         int presenceIndex,
                                          const Options* options);
 
+bool IsNullable(const FieldDescriptor* descriptor);
+
 // Determines whether the given message is a map entry message,
 // i.e. one implicitly created by protoc due to a map<key, value> field.
 inline bool IsMapEntryMessage(const Descriptor* descriptor) {
@@ -144,6 +146,10 @@
       descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
 }
 
+inline bool IsProto2(const FileDescriptor* descriptor) {
+  return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index d58514c..125bdf1 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -48,9 +48,9 @@
 namespace csharp {
 
 MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
-                                     int fieldOrdinal,
+                                     int presenceIndex,
                                      const Options* options)
-    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+    : FieldGeneratorBase(descriptor, presenceIndex, options) {
 }
 
 MapFieldGenerator::~MapFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h
index 84a33a0..91c99bd 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -44,7 +44,7 @@
 class MapFieldGenerator : public FieldGeneratorBase {
  public:
   MapFieldGenerator(const FieldDescriptor* descriptor,
-                    int fieldOrdinal,
+                    int presenceIndex,
                     const Options* options);
   ~MapFieldGenerator();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 8a4307f..1daae6f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -61,20 +61,27 @@
 MessageGenerator::MessageGenerator(const Descriptor* descriptor,
                                    const Options* options)
     : SourceGeneratorBase(descriptor->file(), options),
-      descriptor_(descriptor) {
-
-  // sorted field names
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_names_.push_back(descriptor_->field(i)->name());
-  }
-  std::sort(field_names_.begin(), field_names_.end());
-
+      descriptor_(descriptor),
+      has_bit_field_count_(0) {
   // fields by number
   for (int i = 0; i < descriptor_->field_count(); i++) {
     fields_by_number_.push_back(descriptor_->field(i));
   }
   std::sort(fields_by_number_.begin(), fields_by_number_.end(),
             CompareFieldNumbers);
+
+  if (IsProto2(descriptor_->file())) {
+    int primitiveCount = 0;
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* field = descriptor_->field(i);
+      if (!IsNullable(field)) {
+        primitiveCount++;
+        if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) {
+          has_bit_field_count_++;
+        }
+      }
+    }
+  }
 }
 
 MessageGenerator::~MessageGenerator() {
@@ -88,10 +95,6 @@
   return GetClassName(descriptor_);
 }
 
-const std::vector<std::string>& MessageGenerator::field_names() {
-  return field_names_;
-}
-
 const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() {
   return fields_by_number_;
 }
@@ -123,6 +126,12 @@
   printer->Print(
       "private pb::UnknownFieldSet _unknownFields;\n");
 
+  for (int i = 0; i < has_bit_field_count_; i++) {
+    // don't use arrays since all arrays are heap allocated, saving allocations
+    // use ints instead of bytes since bytes lack bitwise operators, saving casts
+    printer->Print("private int _hasBits$i$;\n", "i", SimpleItoa(i));
+  }
+
   WriteGeneratedCodeAttributes(printer);
 
   printer->Print(
@@ -288,6 +297,9 @@
     vars,
     "public $class_name$($class_name$ other) : this() {\n");
   printer->Indent();
+  for (int i = 0; i < has_bit_field_count_; i++) {
+    printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", SimpleItoa(i));
+  }
   // Clone non-oneof fields first
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (!descriptor_->field(i)->containing_oneof()) {
@@ -559,19 +571,29 @@
   printer->Print("}\n\n"); // method
 }
 
-int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) {
-  for (int i = 0; i < field_names().size(); i++) {
-    if (field_names()[i] == descriptor->name()) {
-      return i;
+// it's a waste of space to track presence for all values, so we only track them if they're not nullable
+int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
+  if (IsNullable(descriptor) || !IsProto2(descriptor_->file())) {
+    return -1;
+  }
+
+  int index = 0;
+  for (int i = 0; i < fields_by_number().size(); i++) {
+    const FieldDescriptor* field = fields_by_number()[i];
+    if (field == descriptor) {
+      return index;
+    }
+    if (!IsNullable(field)) {
+      index++;
     }
   }
-  GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name();
+  GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name();
   return -1;
 }
 
 FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal(
     const FieldDescriptor* descriptor) {
-  return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options());
+  return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options());
 }
 
 }  // namespace csharp
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index e7f3b4d..b20bec3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -57,13 +57,13 @@
 
  private:
   const Descriptor* descriptor_;
-  std::vector<std::string> field_names_;
   std::vector<const FieldDescriptor*> fields_by_number_;
+  int has_bit_field_count_;
 
   void GenerateMessageSerializationMethods(io::Printer* printer);
   void GenerateMergingMethods(io::Printer* printer);
 
-  int GetFieldOrdinal(const FieldDescriptor* descriptor);
+  int GetPresenceIndex(const FieldDescriptor* descriptor);
   FieldGeneratorBase* CreateFieldGeneratorInternal(
       const FieldDescriptor* descriptor);
 
@@ -74,9 +74,6 @@
   std::string class_name();
   std::string full_class_name();
 
-  // field names sorted alphabetically
-  const std::vector<std::string>& field_names();
-
   // field descriptors sorted by number
   const std::vector<const FieldDescriptor*>& fields_by_number();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index cf1b4db..1671460 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -49,11 +49,13 @@
 namespace csharp {
 
 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
-                                             int fieldOrdinal,
+                                             int presenceIndex,
                                              const Options *options)
-    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
-  variables_["has_property_check"] = name() + "_ != null";
-  variables_["has_not_property_check"] = name() + "_ == null";
+    : FieldGeneratorBase(descriptor, presenceIndex, options) {
+  if (!IsProto2(descriptor_->file())) {
+    variables_["has_property_check"] = name() + "_ != null";
+    variables_["has_not_property_check"] = name() + "_ == null";
+  }
 }
 
 MessageFieldGenerator::~MessageFieldGenerator() {
@@ -74,6 +76,26 @@
     "    $name$_ = value;\n"
     "  }\n"
     "}\n");
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(
+      variables_,
+      "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ bool Has$property_name$ {\n"
+      "  get { return $name$_ != null; }\n"
+      "}\n");
+    printer->Print( 
+      variables_, 
+      "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ void Clear$property_name$() {\n"
+      "  $name$_ = null;\n"
+      "}\n");
+  }
 }
 
 void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -81,7 +103,7 @@
     variables_,
     "if (other.$has_property_check$) {\n"
     "  if ($has_not_property_check$) {\n"
-    "    $name$_ = new $type_name$();\n"
+    "    $property_name$ = new $type_name$();\n"
     "  }\n"
     "  $property_name$.MergeFrom(other.$property_name$);\n"
     "}\n");
@@ -91,10 +113,9 @@
   printer->Print(
     variables_,
     "if ($has_not_property_check$) {\n"
-    "  $name$_ = new $type_name$();\n"
+    "  $property_name$ = new $type_name$();\n"
     "}\n"
-    // TODO(jonskeet): Do we really need merging behaviour like this?
-    "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP...
+    "input.ReadMessage($property_name$);\n");
 }
 
 void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
@@ -130,7 +151,6 @@
     variables_,
     "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
 }
-
 void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
   printer->Print(variables_,
     "$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n");
@@ -147,9 +167,9 @@
 
 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
     const FieldDescriptor* descriptor,
-	  int fieldOrdinal,
+	  int presenceIndex,
     const Options *options)
-    : MessageFieldGenerator(descriptor, fieldOrdinal, options) {
+    : MessageFieldGenerator(descriptor, presenceIndex, options) {
   SetCommonOneofFieldVariables(&variables_);
 }
 
@@ -169,6 +189,28 @@
     "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
     "  }\n"
     "}\n");
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(
+      variables_,
+      "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ bool Has$property_name$ {\n"
+      "  get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+      "}\n");
+    printer->Print(
+      variables_,
+      "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ void Clear$property_name$() {\n"
+      "  if ($has_property_check$) {\n"
+      "    Clear$oneof_property_name$();\n"
+      "  }\n"
+      "}\n");
+  }
 }
 
 void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -187,7 +229,7 @@
     "if ($has_property_check$) {\n"
     "  subBuilder.MergeFrom($property_name$);\n"
     "}\n"
-    "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP
+    "input.ReadMessage(subBuilder);\n"
     "$property_name$ = subBuilder;\n");
 }
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
index c41ee88..104fb02 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -44,7 +44,7 @@
 class MessageFieldGenerator : public FieldGeneratorBase {
  public:
   MessageFieldGenerator(const FieldDescriptor* descriptor,
-                        int fieldOrdinal,
+                        int presenceIndex,
                         const Options *options);
   ~MessageFieldGenerator();
 
@@ -68,7 +68,7 @@
 class MessageOneofFieldGenerator : public MessageFieldGenerator {
  public:
   MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
-                             int fieldOrdinal,
+                             int presenceIndex,
                              const Options *options);
   ~MessageOneofFieldGenerator();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index c3003e3..b83468d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -49,12 +49,12 @@
 namespace csharp {
 
 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
-    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+    const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+    : FieldGeneratorBase(descriptor, presenceIndex, options) {
   // TODO(jonskeet): Make this cleaner...
   is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
       && descriptor->type() != FieldDescriptor::TYPE_BYTES;
-  if (!is_value_type) {
+  if (!is_value_type && !IsProto2(descriptor_->file())) {
     variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
     variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
   }
@@ -67,16 +67,44 @@
   // TODO(jonskeet): Work out whether we want to prevent the fields from ever being
   // null, or whether we just handle it, in the cases of bytes and string.
   // (Basically, should null-handling code be in the getter or the setter?)
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(
+      variables_, 
+      "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n");
+  }
+
   printer->Print(
     variables_,
     "private $type_name$ $name_def_message$;\n");
+
   WritePropertyDocComment(printer, descriptor_);
   AddPublicMemberAttributes(printer);
-  printer->Print(
-    variables_,
-    "$access_level$ $type_name$ $property_name$ {\n"
-    "  get { return $name$_; }\n"
-    "  set {\n");
+  if (IsProto2(descriptor_->file())) {
+    if (presenceIndex_ == -1) {
+      printer->Print(
+        variables_,
+        "$access_level$ $type_name$ $property_name$ {\n"
+        "  get { return $name$_ ?? $property_name$DefaultValue; }\n"
+        "  set {\n");
+    } else {
+      printer->Print(
+        variables_,
+        "$access_level$ $type_name$ $property_name$ {\n"
+        "  get { if ($has_field_check$) { return $name$_; } else { return $property_name$DefaultValue; } }\n"
+        "  set {\n");
+    }
+  } else {
+    printer->Print(
+      variables_,
+      "$access_level$ $type_name$ $property_name$ {\n"
+      "  get { return $name$_; }\n"
+      "  set {\n");
+  }
+  if (presenceIndex_ != -1) {
+    printer->Print(
+      variables_,
+      "    $set_has_field$;\n");
+  }
   if (is_value_type) {
     printer->Print(
       variables_,
@@ -89,6 +117,36 @@
   printer->Print(
     "  }\n"
     "}\n");
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(variables_, "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_, 
+      "$access_level$ bool Has$property_name$ {\n"
+      "  get { return ");
+    if (IsNullable(descriptor_)) {
+      printer->Print(
+        variables_,
+        "$name$_ != null; }\n}\n");
+    } else {
+      printer->Print(
+        variables_,
+        "$has_field_check$; }\n}\n");
+    }
+  }
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(variables_, "/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ void Clear$property_name$() {\n");
+    if (IsNullable(descriptor_)) {
+      printer->Print(variables_, "  $name$_ = null;\n");
+    } else {
+      printer->Print(variables_, "  $clear_has_field$;\n");
+    }
+    printer->Print("}\n");
+  }
 }
 
 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -172,8 +230,8 @@
 }
 
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
-    : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
+    const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+    : PrimitiveFieldGenerator(descriptor, presenceIndex, options) {
   SetCommonOneofFieldVariables(&variables_);
 }
 
@@ -188,20 +246,42 @@
     "$access_level$ $type_name$ $property_name$ {\n"
     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
     "  set {\n");
-    if (is_value_type) {
-      printer->Print(
-        variables_,
-        "    $oneof_name$_ = value;\n");
-    } else {
-      printer->Print(
-        variables_,
-        "    $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
-    }
+  if (is_value_type) {
     printer->Print(
       variables_,
-      "    $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
+      "    $oneof_name$_ = value;\n");
+  } else {
+    printer->Print(
+      variables_,
+      "    $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
+  }
+  printer->Print(
+    variables_,
+    "    $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
+    "  }\n"
+    "}\n");
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(
+      variables_,
+      "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ bool Has$property_name$ {\n"
+      "  get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+      "}\n");
+    printer->Print(
+      variables_,
+      "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ void Clear$property_name$() {\n"
+      "  if ($has_property_check$) {\n"
+      "    Clear$oneof_property_name$();\n"
       "  }\n"
       "}\n");
+  }
 }
 
 void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
index ca7b8b3..010ceb2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -46,7 +46,7 @@
 class PrimitiveFieldGenerator : public FieldGeneratorBase {
  public:
   PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
-                          int fieldOrdinal,
+                          int presenceIndex,
                           const Options *options);
   ~PrimitiveFieldGenerator();
 
@@ -72,7 +72,7 @@
 class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
  public:
   PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
-                               int fieldOrdinal,
+                               int presenceIndex,
                                const Options *options);
   ~PrimitiveOneofFieldGenerator();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
index 683c4b0..a69e97b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -48,8 +48,8 @@
 namespace csharp {
 
 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
-    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+    const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+    : FieldGeneratorBase(descriptor, presenceIndex, options) {
 }
 
 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
index 819b583..5825222 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -46,7 +46,7 @@
 class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
  public:
   RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
-                             int fieldOrdinal,
+                             int presenceIndex,
                              const Options *options);
   ~RepeatedEnumFieldGenerator();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
index 90af569..d421659 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -49,8 +49,8 @@
 namespace csharp {
 
 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
-    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+    const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+    : FieldGeneratorBase(descriptor, presenceIndex, options) {
 }
 
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {
@@ -67,11 +67,11 @@
   // function, but it doesn't seem worth it for just this.
   if (IsWrapperType(descriptor_)) {
     std::unique_ptr<FieldGeneratorBase> single_generator(
-      new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
+      new WrapperFieldGenerator(descriptor_, presenceIndex_, this->options()));
     single_generator->GenerateCodecCode(printer);
   } else {
     std::unique_ptr<FieldGeneratorBase> single_generator(
-      new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options()));
+      new MessageFieldGenerator(descriptor_, presenceIndex_, this->options()));
     single_generator->GenerateCodecCode(printer);
   }
   printer->Print(";\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
index 6e33648..ebc760f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -46,7 +46,7 @@
 class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
  public:
   RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
-                                int fieldOrdinal,
+                                int presenceIndex,
                                 const Options *options);
   ~RepeatedMessageFieldGenerator();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
index cd91506..bc25627 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -48,8 +48,8 @@
 namespace csharp {
 
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
-    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+    const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+    : FieldGeneratorBase(descriptor, presenceIndex, options) {
 }
 
 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {
diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
index a59348a..340688e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -43,7 +43,7 @@
 
 class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
  public:
-  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options);
+  RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int presenceIndex, const Options *options);
   ~RepeatedPrimitiveFieldGenerator();
 
   virtual void GenerateCloningCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index 047edf7..1dcbf97 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -48,8 +48,8 @@
 namespace csharp {
 
 WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
-                                       int fieldOrdinal, const Options *options)
-    : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
+                                       int presenceIndex, const Options *options)
+    : FieldGeneratorBase(descriptor, presenceIndex, options) {
   variables_["has_property_check"] = name() + "_ != null";
   variables_["has_not_property_check"] = name() + "_ == null";
   const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0);
@@ -81,7 +81,27 @@
     "  set {\n"
     "    $name$_ = value;\n"
     "  }\n"
-    "}\n");
+    "}\n\n");
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(
+      variables_,
+      "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ bool Has$property_name$ {\n"
+      "  get { return $name$_ != null; }\n"
+      "}\n\n");
+    printer->Print(
+      variables_,
+      "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ void Clear$property_name$() {\n"
+      "  $name$_ = null;\n"
+      "}\n");
+  }
 }
 
 void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) {
@@ -163,8 +183,8 @@
 }
 
 WrapperOneofFieldGenerator::WrapperOneofFieldGenerator(
-    const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
-    : WrapperFieldGenerator(descriptor, fieldOrdinal, options) {
+    const FieldDescriptor* descriptor, int presenceIndex, const Options *options)
+    : WrapperFieldGenerator(descriptor, presenceIndex, options) {
     SetCommonOneofFieldVariables(&variables_);
 }
 
@@ -189,6 +209,28 @@
     "    $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"
     "  }\n"
     "}\n");
+  if (IsProto2(descriptor_->file())) {
+    printer->Print(
+      variables_,
+      "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ bool Has$property_name$ {\n"
+      "  get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n"
+      "}\n");
+    printer->Print(
+      variables_,
+      "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n");
+    AddPublicMemberAttributes(printer);
+    printer->Print(
+      variables_,
+      "$access_level$ void Clear$property_name$() {\n"
+      "  if ($has_property_check$) {\n"
+      "    Clear$oneof_property_name$();\n"
+      "  }\n"
+      "}\n");
+  }
 }
 
 void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
index 452531f..08cae54 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -46,7 +46,7 @@
 class WrapperFieldGenerator : public FieldGeneratorBase {
  public:
   WrapperFieldGenerator(const FieldDescriptor* descriptor,
-                        int fieldOrdinal,
+                        int presenceIndex,
                         const Options *options);
   ~WrapperFieldGenerator();
 
@@ -70,7 +70,7 @@
 class WrapperOneofFieldGenerator : public WrapperFieldGenerator {
  public:
   WrapperOneofFieldGenerator(const FieldDescriptor* descriptor,
-                             int fieldOrdinal,
+                             int presenceIndex,
                              const Options *options);
   ~WrapperOneofFieldGenerator();