Selaa lähdekoodia

merged issue-22

csharptest 14 vuotta sitten
vanhempi
commit
8c2b8d11de
36 muutettua tiedostoa jossa 4499 lisäystä ja 1035 poistoa
  1. 141 35
      src/AddressBook/AddressBookProtos.cs
  2. 2 0
      src/ProtoGen/EnumFieldGenerator.cs
  3. 4 0
      src/ProtoGen/MessageFieldGenerator.cs
  4. 43 12
      src/ProtoGen/MessageGenerator.cs
  5. 2 0
      src/ProtoGen/PrimitiveFieldGenerator.cs
  6. 5 1
      src/ProtoGen/RepeatedEnumFieldGenerator.cs
  7. 7 1
      src/ProtoGen/RepeatedMessageFieldGenerator.cs
  8. 5 1
      src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
  9. 0 16
      src/ProtocolBuffers.Test/GeneratedMessageTest.cs
  10. 1 0
      src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  11. 157 0
      src/ProtocolBuffers.Test/ReusableBuilderTest.cs
  12. 45 11
      src/ProtocolBuffers.Test/TestProtos/UnitTestCSharpOptionsProtoFile.cs
  13. 425 116
      src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs
  14. 50 12
      src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
  15. 318 82
      src/ProtocolBuffers.Test/TestProtos/UnitTestExtrasIssuesProtoFile.cs
  16. 195 23
      src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSizeProtoFile.cs
  17. 195 23
      src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSpeedProtoFile.cs
  18. 41 11
      src/ProtocolBuffers.Test/TestProtos/UnitTestImportLiteProtoFile.cs
  19. 41 11
      src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
  20. 253 67
      src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
  21. 41 11
      src/ProtocolBuffers.Test/TestProtos/UnitTestNoGenericServicesProtoFile.cs
  22. 123 33
      src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs
  23. 249 51
      src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
  24. 181 47
      src/ProtocolBuffers.Test/TestProtos/UnitTestRpcInterop.cs
  25. 281 71
      src/ProtocolBuffers.Test/TestProtos/UnitTestXmlSerializerTestProtoFile.cs
  26. 190 44
      src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
  27. 282 61
      src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  28. 3 8
      src/ProtocolBuffers/GeneratedBuilder.cs
  29. 1 6
      src/ProtocolBuffers/GeneratedBuilderLite.cs
  30. 355 88
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasFullProtoFile.cs
  31. 240 58
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasLiteProtoFile.cs
  32. 41 11
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportLiteProtoFile.cs
  33. 41 11
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportProtoFile.cs
  34. 43 11
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteImportNonLiteProtoFile.cs
  35. 249 51
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteProtoFile.cs
  36. 249 51
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestProtoFile.cs

+ 141 - 35
src/AddressBook/AddressBookProtos.cs

@@ -225,7 +225,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
         public override Builder ToBuilder() { return CreateBuilder(this); }
         public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(PhoneNumber prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -235,21 +235,48 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance ?? new PhoneNumber();
+            builderIsReadOnly = result == DefaultInstance;
+          }
+          internal Builder(PhoneNumber cloneFrom) {
+            result = cloneFrom;
+            builderIsReadOnly = true;
+          }
           
-          PhoneNumber result = new PhoneNumber();
+          bool builderIsReadOnly;
+          PhoneNumber result;
+          
+          private PhoneNumber PrepareBuilder() {
+            if (builderIsReadOnly) {
+              PhoneNumber original = result;
+              result = new PhoneNumber();
+              builderIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override PhoneNumber MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new PhoneNumber();
+            result = DefaultInstance ?? new PhoneNumber();
+            builderIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (builderIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override pbd::MessageDescriptor DescriptorForType {
@@ -261,12 +288,11 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           }
           
           public override PhoneNumber BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (builderIsReadOnly) {
+              return result;
             }
-            PhoneNumber returnMe = result;
-            result = null;
-            return returnMe;
+            builderIsReadOnly = true;
+            return result;
           }
           
           public override Builder MergeFrom(pb::IMessage other) {
@@ -280,6 +306,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           
           public override Builder MergeFrom(PhoneNumber other) {
             if (other == global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasNumber) {
               Number = other.Number;
             }
@@ -295,6 +322,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             pb::UnknownFieldSet.Builder unknownFields = null;
             uint tag;
             string field_name;
@@ -363,11 +391,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           }
           public Builder SetNumber(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasNumber = true;
             result.number_ = value;
             return this;
           }
           public Builder ClearNumber() {
+            PrepareBuilder();
             result.hasNumber = false;
             result.number_ = "";
             return this;
@@ -381,11 +411,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
             set { SetType(value); }
           }
           public Builder SetType(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType value) {
+            PrepareBuilder();
             result.hasType = true;
             result.type_ = value;
             return this;
           }
           public Builder ClearType() {
+            PrepareBuilder();
             result.hasType = false;
             result.type_ = global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME;
             return this;
@@ -529,7 +561,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(Person prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -539,21 +571,48 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new Person();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(Person cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      Person result = new Person();
+      bool builderIsReadOnly;
+      Person result;
+      
+      private Person PrepareBuilder() {
+        if (builderIsReadOnly) {
+          Person original = result;
+          result = new Person();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override Person MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new Person();
+        result = DefaultInstance ?? new Person();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -565,13 +624,12 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override Person BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.phone_.MakeReadOnly();
-        Person returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -585,6 +643,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       
       public override Builder MergeFrom(Person other) {
         if (other == global::Google.ProtocolBuffers.Examples.AddressBook.Person.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasName) {
           Name = other.Name;
         }
@@ -606,6 +665,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -674,11 +734,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       public Builder SetName(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasName = true;
         result.name_ = value;
         return this;
       }
       public Builder ClearName() {
+        PrepareBuilder();
         result.hasName = false;
         result.name_ = "";
         return this;
@@ -692,11 +754,13 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
         set { SetId(value); }
       }
       public Builder SetId(int value) {
+        PrepareBuilder();
         result.hasId = true;
         result.id_ = value;
         return this;
       }
       public Builder ClearId() {
+        PrepareBuilder();
         result.hasId = false;
         result.id_ = 0;
         return this;
@@ -711,18 +775,20 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       public Builder SetEmail(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasEmail = true;
         result.email_ = value;
         return this;
       }
       public Builder ClearEmail() {
+        PrepareBuilder();
         result.hasEmail = false;
         result.email_ = "";
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> PhoneList {
-        get { return result.phone_; }
+        get { return PrepareBuilder().phone_; }
       }
       public int PhoneCount {
         get { return result.PhoneCount; }
@@ -732,29 +798,35 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_[index] = value;
         return this;
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_.Add(value);
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangePhone(scg::IEnumerable<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> values) {
+        PrepareBuilder();
         result.phone_.Add(values);
         return this;
       }
       public Builder ClearPhone() {
+        PrepareBuilder();
         result.phone_.Clear();
         return this;
       }
@@ -872,7 +944,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(AddressBook prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -882,21 +954,48 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new AddressBook();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(AddressBook cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      AddressBook result = new AddressBook();
+      bool builderIsReadOnly;
+      AddressBook result;
+      
+      private AddressBook PrepareBuilder() {
+        if (builderIsReadOnly) {
+          AddressBook original = result;
+          result = new AddressBook();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override AddressBook MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new AddressBook();
+        result = DefaultInstance ?? new AddressBook();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -908,13 +1007,12 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override AddressBook BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.person_.MakeReadOnly();
-        AddressBook returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -928,6 +1026,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       
       public override Builder MergeFrom(AddressBook other) {
         if (other == global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.person_.Count != 0) {
           result.person_.Add(other.person_);
         }
@@ -940,6 +1039,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -988,7 +1088,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person> PersonList {
-        get { return result.person_; }
+        get { return PrepareBuilder().person_; }
       }
       public int PersonCount {
         get { return result.PersonCount; }
@@ -998,29 +1098,35 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       public Builder SetPerson(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.person_[index] = value;
         return this;
       }
       public Builder SetPerson(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.person_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddPerson(global::Google.ProtocolBuffers.Examples.AddressBook.Person value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.person_.Add(value);
         return this;
       }
       public Builder AddPerson(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.person_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangePerson(scg::IEnumerable<global::Google.ProtocolBuffers.Examples.AddressBook.Person> values) {
+        PrepareBuilder();
         result.person_.Add(values);
         return this;
       }
       public Builder ClearPerson() {
+        PrepareBuilder();
         result.person_.Clear();
         return this;
       }

+ 2 - 0
src/ProtoGen/EnumFieldGenerator.cs

@@ -72,12 +72,14 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = false;", PropertyName);
             writer.WriteLine("  result.{0}_ = {1};", Name, DefaultValue);
             writer.WriteLine("  return this;");

+ 4 - 0
src/ProtoGen/MessageFieldGenerator.cs

@@ -73,6 +73,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = value;", Name);
             writer.WriteLine("  return this;");
@@ -80,6 +81,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
             AddNullCheck(writer, "builderForValue");
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = builderForValue.Build();", Name);
             writer.WriteLine("  return this;");
@@ -87,6 +89,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Merge{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  if (result.has{0} &&", PropertyName);
             writer.WriteLine("      result.{0}_ != {1}) {{", Name, DefaultValue);
             writer.WriteLine("      result.{0}_ = {1}.CreateBuilder(result.{0}_).MergeFrom(value).BuildPartial();", Name,
@@ -99,6 +102,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = false;", PropertyName);
             writer.WriteLine("  result.{0}_ = {1};", Name, DefaultValue);
             writer.WriteLine("  return this;");

+ 43 - 12
src/ProtoGen/MessageGenerator.cs

@@ -556,7 +556,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("public override Builder ToBuilder() { return CreateBuilder(this); }");
             writer.WriteLine("public override Builder CreateBuilderForType() { return new Builder(); }");
             writer.WriteLine("public static Builder CreateBuilder({0} prototype) {{", ClassName);
-            writer.WriteLine("  return (Builder) new Builder().MergeFrom(prototype);");
+            writer.WriteLine("  return new Builder(prototype);");
             writer.WriteLine("}");
             writer.WriteLine();
             if (Descriptor.File.CSharpOptions.AddSerializable)
@@ -591,21 +591,52 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         private void GenerateCommonBuilderMethods(TextGenerator writer)
         {
-            writer.WriteLine("public Builder() {{}}", ClassAccessLevel);
+            //default constructor
+            writer.WriteLine("public Builder() {");
+            //Durring static initialization of message, DefaultInstance is expected to return null.
+            writer.WriteLine("  result = DefaultInstance ?? new {0}();", ClassName);
+            writer.WriteLine("  builderIsReadOnly = result == DefaultInstance;");
+            writer.WriteLine("}");
+            //clone constructor
+            writer.WriteLine("internal Builder({0} cloneFrom) {{", ClassName);
+            writer.WriteLine("  result = cloneFrom;");
+            writer.WriteLine("  builderIsReadOnly = true;");
+            writer.WriteLine("}");
+            writer.WriteLine();
+            writer.WriteLine("bool builderIsReadOnly;");
+            writer.WriteLine("{0} result;", ClassName);
+            writer.WriteLine();
+            writer.WriteLine("private {0} PrepareBuilder() {{", ClassName);
+            writer.WriteLine("  if (builderIsReadOnly) {");
+            writer.WriteLine("    {0} original = result;", ClassName);
+            writer.WriteLine("    result = new {0}();", ClassName);
+            writer.WriteLine("    builderIsReadOnly = false;");
+            writer.WriteLine("    MergeFrom(original);");
+            writer.WriteLine("  }");
+            writer.WriteLine("  return result;");
+            writer.WriteLine("}");
             writer.WriteLine();
-            writer.WriteLine("{0} result = new {0}();", ClassName);
+            writer.WriteLine("public override bool IsInitialized {");
+            writer.WriteLine("  get { return result.IsInitialized; }");
+            writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("protected override {0} MessageBeingBuilt {{", ClassName);
-            writer.WriteLine("  get { return result; }");
+            writer.WriteLine("  get { return PrepareBuilder(); }");
             writer.WriteLine("}");
             writer.WriteLine();
+            //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break
             writer.WriteLine("public override Builder Clear() {");
-            writer.WriteLine("  result = new {0}();", ClassName);
+            writer.WriteLine("  result = DefaultInstance ?? new {0}();", ClassName);
+            writer.WriteLine("  builderIsReadOnly = true;");
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             writer.WriteLine();
             writer.WriteLine("public override Builder Clone() {");
-            writer.WriteLine("  return new Builder().MergeFrom(result);");
+            writer.WriteLine("  if (builderIsReadOnly) {");
+            writer.WriteLine("    return new Builder(result);");
+            writer.WriteLine("  } else {");
+            writer.WriteLine("    return new Builder().MergeFrom(result);");
+            writer.WriteLine("  }");
             writer.WriteLine("}");
             writer.WriteLine();
             if (!UseLiteRuntime)
@@ -622,17 +653,15 @@ namespace Google.ProtocolBuffers.ProtoGen
 
             writer.WriteLine("public override {0} BuildPartial() {{", ClassName);
             writer.Indent();
-            writer.WriteLine("if (result == null) {");
-            writer.WriteLine(
-                "  throw new global::System.InvalidOperationException(\"build() has already been called on this Builder\");");
+            writer.WriteLine("if (builderIsReadOnly) {");
+            writer.WriteLine("  return result;");
             writer.WriteLine("}");
             foreach (FieldDescriptor field in Descriptor.Fields)
             {
                 CreateFieldGenerator(field).GenerateBuildingCode(writer);
             }
-            writer.WriteLine("{0} returnMe = result;", ClassName);
-            writer.WriteLine("result = null;");
-            writer.WriteLine("return returnMe;");
+            writer.WriteLine("builderIsReadOnly = true;");
+            writer.WriteLine("return result;");
             writer.Outdent();
             writer.WriteLine("}");
             writer.WriteLine();
@@ -653,6 +682,7 @@ namespace Google.ProtocolBuffers.ProtoGen
                 // fields are set so we can skip the merge.
                 writer.Indent();
                 writer.WriteLine("if (other == {0}.DefaultInstance) return this;", FullClassName);
+                writer.WriteLine("PrepareBuilder();");
                 foreach (FieldDescriptor field in Descriptor.Fields)
                 {
                     CreateFieldGenerator(field).GenerateMergingCode(writer);
@@ -685,6 +715,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine(
                 "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {");
             writer.Indent();
+            writer.WriteLine("PrepareBuilder();");
             if (!UseLiteRuntime)
             {
                 writer.WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;");

+ 2 - 0
src/ProtoGen/PrimitiveFieldGenerator.cs

@@ -74,12 +74,14 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Set{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = true;", PropertyName);
             writer.WriteLine("  result.{0}_ = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.has{0} = false;", PropertyName);
             writer.WriteLine("  result.{0}_ = {1};", Name, DefaultValue);
             writer.WriteLine("  return this;");

+ 5 - 1
src/ProtoGen/RepeatedEnumFieldGenerator.cs

@@ -75,7 +75,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
             AddDeprecatedFlag(writer);
             writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return result.{0}_; }}", Name);
+            writer.WriteLine("  get {{ return PrepareBuilder().{0}_; }}", Name);
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
@@ -87,21 +87,25 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(value);", Name, TypeName);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(values);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Clear();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");

+ 7 - 1
src/ProtoGen/RepeatedMessageFieldGenerator.cs

@@ -71,7 +71,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
             AddDeprecatedFlag(writer);
             writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return result.{0}_; }}", Name);
+            writer.WriteLine("  get {{ return PrepareBuilder().{0}_; }}", Name);
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
@@ -84,6 +84,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
@@ -91,12 +92,14 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1}.Builder builderForValue) {{", PropertyName, TypeName);
             AddNullCheck(writer, "builderForValue");
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = builderForValue.Build();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(value);", Name, TypeName);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
@@ -104,16 +107,19 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Add{0}({1}.Builder builderForValue) {{", PropertyName, TypeName);
             AddNullCheck(writer, "builderForValue");
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(builderForValue.Build());", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(values);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Clear();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");

+ 5 - 1
src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs

@@ -75,7 +75,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
             AddPublicMemberAttributes(writer);
             writer.WriteLine("public pbc::IPopsicleList<{0}> {1}List {{", TypeName, PropertyName);
-            writer.WriteLine("  get {{ return result.{0}_; }}", Name);
+            writer.WriteLine("  get {{ return PrepareBuilder().{0}_; }}", Name);
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public int {0}Count {{", PropertyName);
@@ -88,22 +88,26 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_[index] = value;", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
             AddNullCheck(writer);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(value);", Name, TypeName);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddPublicMemberAttributes(writer);
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Add(values);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             AddDeprecatedFlag(writer);
             writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  result.{0}_.Clear();", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");

+ 0 - 16
src/ProtocolBuffers.Test/GeneratedMessageTest.cs

@@ -111,22 +111,6 @@ namespace Google.ProtocolBuffers
             }
         }
 
-        [Test]
-        public void DoubleBuildError()
-        {
-            TestAllTypes.Builder builder = new TestAllTypes.Builder();
-            builder.Build();
-            try
-            {
-                builder.Build();
-                Assert.Fail("Should have thrown exception.");
-            }
-            catch (InvalidOperationException)
-            {
-                // Success.
-            }
-        }
-
         [Test]
         public void DefaultInstance()
         {

+ 1 - 0
src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj

@@ -103,6 +103,7 @@
     <Compile Include="NameHelpersTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ReflectionTester.cs" />
+    <Compile Include="ReusableBuilderTest.cs" />
     <Compile Include="SerializableTest.cs" />
     <Compile Include="ServiceTest.cs" />
     <Compile Include="TestCornerCases.cs" />

+ 157 - 0
src/ProtocolBuffers.Test/ReusableBuilderTest.cs

@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Google.ProtocolBuffers.Collections;
+using NUnit.Framework;
+using Google.ProtocolBuffers.TestProtos;
+using Google.ProtocolBuffers.Serialization;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class ReusableBuilderTest
+    {
+        [Test]
+        public void TestModifyDefaultInstance()
+        {
+            //verify that the default instance has correctly been marked as read-only
+            Assert.AreEqual(typeof(PopsicleList<bool>), TestAllTypes.DefaultInstance.RepeatedBoolList.GetType());
+            PopsicleList<bool> list = (PopsicleList<bool>)TestAllTypes.DefaultInstance.RepeatedBoolList;
+            Assert.IsTrue(list.IsReadOnly);
+        }
+
+        [Test]
+        public void TestUnmodifiedDefaultInstance()
+        {
+            //Simply calling ToBuilder().Build() no longer creates a copy of the message
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void BuildMultipleWithoutChange()
+        {
+            //Calling Build() or BuildPartial() does not require a copy of the message
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            builder.SetDefaultBool(true);
+
+            TestAllTypes first = builder.BuildPartial();
+            //Still the same instance?
+            Assert.IsTrue(ReferenceEquals(first, builder.Build()));
+            //Still the same instance?
+            Assert.IsTrue(ReferenceEquals(first, builder.BuildPartial().ToBuilder().Build()));
+        }
+
+        [Test]
+        public void MergeFromDefaultInstance()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.MergeFrom(TestAllTypes.DefaultInstance);
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void BuildNewBuilderIsDefaultInstance()
+        {
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, new TestAllTypes.Builder().Build()));
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, TestAllTypes.CreateBuilder().Build()));
+            //last test, if you clear a builder it reverts to default instance
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance,
+                TestAllTypes.CreateBuilder().SetOptionalBool(true).Build().ToBuilder().Clear().Build()));
+        }
+
+        [Test]
+        public void BuildModifyAndRebuild()
+        {
+            TestAllTypes.Builder b1 = new TestAllTypes.Builder();
+            b1.SetDefaultInt32(1);
+            b1.AddRepeatedInt32(2);
+            b1.SetOptionalForeignMessage(ForeignMessage.DefaultInstance);
+
+            TestAllTypes m1 = b1.Build();
+
+            b1.SetDefaultInt32(5);
+            b1.AddRepeatedInt32(6);
+            b1.SetOptionalForeignMessage(b1.OptionalForeignMessage.ToBuilder().SetC(7));
+
+            TestAllTypes m2 = b1.Build();
+            
+            Assert.AreEqual("{\"optional_foreign_message\":{},\"repeated_int32\":[2],\"default_int32\":1}", m1.ToJson());
+            Assert.AreEqual("{\"optional_foreign_message\":{\"c\":7},\"repeated_int32\":[2,6],\"default_int32\":5}", m2.ToJson());
+        }
+
+        [Test]
+        public void CloneOnChangePrimitive()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.SetDefaultBool(true);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnAddRepeatedBool()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.AddRepeatedBool(true);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnGetRepeatedBoolList()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            GC.KeepAlive(builder.RepeatedBoolList);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnChangeMessage()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.SetOptionalForeignMessage(new ForeignMessage.Builder());
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnClearMessage()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.ClearOptionalForeignMessage();
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnGetRepeatedForeignMessageList()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            GC.KeepAlive(builder.RepeatedForeignMessageList);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnChangeEnumValue()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.SetOptionalForeignEnum(ForeignEnum.FOREIGN_BAR);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+        [Test]
+        public void CloneOnGetRepeatedForeignEnumList()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            GC.KeepAlive(builder.RepeatedForeignEnumList);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+    }
+}

+ 45 - 11
src/ProtocolBuffers.Test/TestProtos/UnitTestCSharpOptionsProtoFile.cs

@@ -191,7 +191,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(OptionsMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -201,21 +201,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new OptionsMessage();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(OptionsMessage cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      OptionsMessage result;
       
-      OptionsMessage result = new OptionsMessage();
+      private OptionsMessage PrepareBuilder() {
+        if (builderIsReadOnly) {
+          OptionsMessage original = result;
+          result = new OptionsMessage();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override OptionsMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new OptionsMessage();
+        result = DefaultInstance ?? new OptionsMessage();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -227,12 +254,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override OptionsMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        OptionsMessage returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -246,6 +272,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(OptionsMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.OptionsMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNormal) {
           Normal = other.Normal;
         }
@@ -264,6 +291,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -328,11 +356,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetNormal(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasNormal = true;
         result.normal_ = value;
         return this;
       }
       public Builder ClearNormal() {
+        PrepareBuilder();
         result.hasNormal = false;
         result.normal_ = "";
         return this;
@@ -347,11 +377,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetOptionsMessage_(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasOptionsMessage_ = true;
         result.optionsMessage_ = value;
         return this;
       }
       public Builder ClearOptionsMessage_() {
+        PrepareBuilder();
         result.hasOptionsMessage_ = false;
         result.optionsMessage_ = "";
         return this;
@@ -366,11 +398,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetCustomName(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasCustomName = true;
         result.customized_ = value;
         return this;
       }
       public Builder ClearCustomName() {
+        PrepareBuilder();
         result.hasCustomName = false;
         result.customized_ = "";
         return this;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 425 - 116
src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs


+ 50 - 12
src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs

@@ -187,7 +187,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestEmbedOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -197,21 +197,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestEmbedOptimizedForSize();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestEmbedOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      TestEmbedOptimizedForSize result;
       
-      TestEmbedOptimizedForSize result = new TestEmbedOptimizedForSize();
+      private TestEmbedOptimizedForSize PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestEmbedOptimizedForSize original = result;
+          result = new TestEmbedOptimizedForSize();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestEmbedOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestEmbedOptimizedForSize();
+        result = DefaultInstance ?? new TestEmbedOptimizedForSize();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -223,13 +250,12 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestEmbedOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.repeatedMessage_.MakeReadOnly();
-        TestEmbedOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -243,6 +269,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestEmbedOptimizedForSize other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasOptionalMessage) {
           MergeOptionalMessage(other.OptionalMessage);
         }
@@ -258,6 +285,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -323,18 +351,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasOptionalMessage = true;
         result.optionalMessage_ = value;
         return this;
       }
       public Builder SetOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasOptionalMessage = true;
         result.optionalMessage_ = builderForValue.Build();
         return this;
       }
       public Builder MergeOptionalMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasOptionalMessage &&
             result.optionalMessage_ != global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance) {
             result.optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.CreateBuilder(result.optionalMessage_).MergeFrom(value).BuildPartial();
@@ -345,13 +376,14 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearOptionalMessage() {
+        PrepareBuilder();
         result.hasOptionalMessage = false;
         result.optionalMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance;
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> RepeatedMessageList {
-        get { return result.repeatedMessage_; }
+        get { return PrepareBuilder().repeatedMessage_; }
       }
       public int RepeatedMessageCount {
         get { return result.RepeatedMessageCount; }
@@ -361,29 +393,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetRepeatedMessage(int index, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.repeatedMessage_[index] = value;
         return this;
       }
       public Builder SetRepeatedMessage(int index, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.repeatedMessage_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.repeatedMessage_.Add(value);
         return this;
       }
       public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.repeatedMessage_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeRepeatedMessage(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> values) {
+        PrepareBuilder();
         result.repeatedMessage_.Add(values);
         return this;
       }
       public Builder ClearRepeatedMessage() {
+        PrepareBuilder();
         result.repeatedMessage_.Clear();
         return this;
       }

+ 318 - 82
src/ProtocolBuffers.Test/TestProtos/UnitTestExtrasIssuesProtoFile.cs

@@ -224,7 +224,7 @@ namespace UnitTest.Issues.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(A prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -234,21 +234,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new A();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(A cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      A result;
+      
+      private A PrepareBuilder() {
+        if (builderIsReadOnly) {
+          A original = result;
+          result = new A();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      A result = new A();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override A MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new A();
+        result = DefaultInstance ?? new A();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -260,12 +287,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override A BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        A returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -279,6 +305,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(A other) {
         if (other == global::UnitTest.Issues.TestProtos.A.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasA_) {
           A_ = other.A_;
         }
@@ -291,6 +318,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -346,11 +374,13 @@ namespace UnitTest.Issues.TestProtos {
         set { SetA_(value); }
       }
       public Builder SetA_(int value) {
+        PrepareBuilder();
         result.hasA_ = true;
         result.a_ = value;
         return this;
       }
       public Builder ClearA_() {
+        PrepareBuilder();
         result.hasA_ = false;
         result.a_ = 0;
         return this;
@@ -464,7 +494,7 @@ namespace UnitTest.Issues.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(B prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -474,21 +504,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new B();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(B cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      B result;
+      
+      private B PrepareBuilder() {
+        if (builderIsReadOnly) {
+          B original = result;
+          result = new B();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      B result = new B();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override B MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new B();
+        result = DefaultInstance ?? new B();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -500,12 +557,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override B BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        B returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -519,6 +575,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(B other) {
         if (other == global::UnitTest.Issues.TestProtos.B.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasB_) {
           B_ = other.B_;
         }
@@ -531,6 +588,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -586,11 +644,13 @@ namespace UnitTest.Issues.TestProtos {
         set { SetB_(value); }
       }
       public Builder SetB_(int value) {
+        PrepareBuilder();
         result.hasB_ = true;
         result.b_ = value;
         return this;
       }
       public Builder ClearB_() {
+        PrepareBuilder();
         result.hasB_ = false;
         result.b_ = 0;
         return this;
@@ -704,7 +764,7 @@ namespace UnitTest.Issues.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(AB prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -714,21 +774,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new AB();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(AB cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      AB result;
+      
+      private AB PrepareBuilder() {
+        if (builderIsReadOnly) {
+          AB original = result;
+          result = new AB();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      AB result = new AB();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override AB MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new AB();
+        result = DefaultInstance ?? new AB();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -740,12 +827,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override AB BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        AB returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -759,6 +845,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(AB other) {
         if (other == global::UnitTest.Issues.TestProtos.AB.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasAB_) {
           AB_ = other.AB_;
         }
@@ -771,6 +858,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -826,11 +914,13 @@ namespace UnitTest.Issues.TestProtos {
         set { SetAB_(value); }
       }
       public Builder SetAB_(int value) {
+        PrepareBuilder();
         result.hasAB_ = true;
         result.aB_ = value;
         return this;
       }
       public Builder ClearAB_() {
+        PrepareBuilder();
         result.hasAB_ = false;
         result.aB_ = 0;
         return this;
@@ -946,7 +1036,7 @@ namespace UnitTest.Issues.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(NumberField prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -956,21 +1046,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new NumberField();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(NumberField cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      NumberField result;
       
-      NumberField result = new NumberField();
+      private NumberField PrepareBuilder() {
+        if (builderIsReadOnly) {
+          NumberField original = result;
+          result = new NumberField();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override NumberField MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new NumberField();
+        result = DefaultInstance ?? new NumberField();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -982,12 +1099,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override NumberField BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        NumberField returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1001,6 +1117,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(NumberField other) {
         if (other == global::UnitTest.Issues.TestProtos.NumberField.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.Has_01) {
           _01 = other._01;
         }
@@ -1013,6 +1130,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1070,11 +1188,13 @@ namespace UnitTest.Issues.TestProtos {
       }
       [global::System.CLSCompliant(false)]
       public Builder Set_01(int value) {
+        PrepareBuilder();
         result.has_01 = true;
         result._01_ = value;
         return this;
       }
       public Builder Clear_01() {
+        PrepareBuilder();
         result.has_01 = false;
         result._01_ = 0;
         return this;
@@ -1241,7 +1361,7 @@ namespace UnitTest.Issues.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(NegativeEnumMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1251,21 +1371,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new NegativeEnumMessage();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(NegativeEnumMessage cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      NegativeEnumMessage result;
+      
+      private NegativeEnumMessage PrepareBuilder() {
+        if (builderIsReadOnly) {
+          NegativeEnumMessage original = result;
+          result = new NegativeEnumMessage();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      NegativeEnumMessage result = new NegativeEnumMessage();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override NegativeEnumMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new NegativeEnumMessage();
+        result = DefaultInstance ?? new NegativeEnumMessage();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1277,14 +1424,13 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override NegativeEnumMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.values_.MakeReadOnly();
         result.packedValues_.MakeReadOnly();
-        NegativeEnumMessage returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1298,6 +1444,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(NegativeEnumMessage other) {
         if (other == global::UnitTest.Issues.TestProtos.NegativeEnumMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasValue) {
           Value = other.Value;
         }
@@ -1316,6 +1463,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1407,18 +1555,20 @@ namespace UnitTest.Issues.TestProtos {
         set { SetValue(value); }
       }
       public Builder SetValue(global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
         result.hasValue = true;
         result.value_ = value;
         return this;
       }
       public Builder ClearValue() {
+        PrepareBuilder();
         result.hasValue = false;
         result.value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.FiveBelow;
         return this;
       }
       
       public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum> ValuesList {
-        get { return result.values_; }
+        get { return PrepareBuilder().values_; }
       }
       public int ValuesCount {
         get { return result.ValuesCount; }
@@ -1427,24 +1577,28 @@ namespace UnitTest.Issues.TestProtos {
         return result.GetValues(index);
       }
       public Builder SetValues(int index, global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
         result.values_[index] = value;
         return this;
       }
       public Builder AddValues(global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
         result.values_.Add(value);
         return this;
       }
       public Builder AddRangeValues(scg::IEnumerable<global::UnitTest.Issues.TestProtos.NegativeEnum> values) {
+        PrepareBuilder();
         result.values_.Add(values);
         return this;
       }
       public Builder ClearValues() {
+        PrepareBuilder();
         result.values_.Clear();
         return this;
       }
       
       public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValuesList {
-        get { return result.packedValues_; }
+        get { return PrepareBuilder().packedValues_; }
       }
       public int PackedValuesCount {
         get { return result.PackedValuesCount; }
@@ -1453,18 +1607,22 @@ namespace UnitTest.Issues.TestProtos {
         return result.GetPackedValues(index);
       }
       public Builder SetPackedValues(int index, global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
         result.packedValues_[index] = value;
         return this;
       }
       public Builder AddPackedValues(global::UnitTest.Issues.TestProtos.NegativeEnum value) {
+        PrepareBuilder();
         result.packedValues_.Add(value);
         return this;
       }
       public Builder AddRangePackedValues(scg::IEnumerable<global::UnitTest.Issues.TestProtos.NegativeEnum> values) {
+        PrepareBuilder();
         result.packedValues_.Add(values);
         return this;
       }
       public Builder ClearPackedValues() {
+        PrepareBuilder();
         result.packedValues_.Clear();
         return this;
       }
@@ -1561,7 +1719,7 @@ namespace UnitTest.Issues.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(DeprecatedChild prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1571,21 +1729,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new DeprecatedChild();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(DeprecatedChild cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      DeprecatedChild result = new DeprecatedChild();
+      bool builderIsReadOnly;
+      DeprecatedChild result;
+      
+      private DeprecatedChild PrepareBuilder() {
+        if (builderIsReadOnly) {
+          DeprecatedChild original = result;
+          result = new DeprecatedChild();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override DeprecatedChild MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new DeprecatedChild();
+        result = DefaultInstance ?? new DeprecatedChild();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1597,12 +1782,11 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override DeprecatedChild BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        DeprecatedChild returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1616,6 +1800,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(DeprecatedChild other) {
         if (other == global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance) return this;
+        PrepareBuilder();
         this.MergeUnknownFields(other.UnknownFields);
         return this;
       }
@@ -1625,6 +1810,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1889,7 +2075,7 @@ namespace UnitTest.Issues.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(DeprecatedFieldsMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1899,21 +2085,48 @@ namespace UnitTest.Issues.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new DeprecatedFieldsMessage();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(DeprecatedFieldsMessage cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      DeprecatedFieldsMessage result = new DeprecatedFieldsMessage();
+      bool builderIsReadOnly;
+      DeprecatedFieldsMessage result;
+      
+      private DeprecatedFieldsMessage PrepareBuilder() {
+        if (builderIsReadOnly) {
+          DeprecatedFieldsMessage original = result;
+          result = new DeprecatedFieldsMessage();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override DeprecatedFieldsMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new DeprecatedFieldsMessage();
+        result = DefaultInstance ?? new DeprecatedFieldsMessage();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1925,15 +2138,14 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override DeprecatedFieldsMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.primitiveArray_.MakeReadOnly();
         result.messageArray_.MakeReadOnly();
         result.enumArray_.MakeReadOnly();
-        DeprecatedFieldsMessage returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1947,6 +2159,7 @@ namespace UnitTest.Issues.TestProtos {
       
       public override Builder MergeFrom(DeprecatedFieldsMessage other) {
         if (other == global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasPrimitiveValue) {
           PrimitiveValue = other.PrimitiveValue;
         }
@@ -1974,6 +2187,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -2076,12 +2290,14 @@ namespace UnitTest.Issues.TestProtos {
       }
       [global::System.ObsoleteAttribute()]
       public Builder SetPrimitiveValue(int value) {
+        PrepareBuilder();
         result.hasPrimitiveValue = true;
         result.primitiveValue_ = value;
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder ClearPrimitiveValue() {
+        PrepareBuilder();
         result.hasPrimitiveValue = false;
         result.primitiveValue_ = 0;
         return this;
@@ -2089,7 +2305,7 @@ namespace UnitTest.Issues.TestProtos {
       
       [global::System.ObsoleteAttribute()]
       public pbc::IPopsicleList<int> PrimitiveArrayList {
-        get { return result.primitiveArray_; }
+        get { return PrepareBuilder().primitiveArray_; }
       }
       [global::System.ObsoleteAttribute()]
       public int PrimitiveArrayCount {
@@ -2101,21 +2317,25 @@ namespace UnitTest.Issues.TestProtos {
       }
       [global::System.ObsoleteAttribute()]
       public Builder SetPrimitiveArray(int index, int value) {
+        PrepareBuilder();
         result.primitiveArray_[index] = value;
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder AddPrimitiveArray(int value) {
+        PrepareBuilder();
         result.primitiveArray_.Add(value);
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder AddRangePrimitiveArray(scg::IEnumerable<int> values) {
+        PrepareBuilder();
         result.primitiveArray_.Add(values);
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder ClearPrimitiveArray() {
+        PrepareBuilder();
         result.primitiveArray_.Clear();
         return this;
       }
@@ -2132,6 +2352,7 @@ namespace UnitTest.Issues.TestProtos {
       [global::System.ObsoleteAttribute()]
       public Builder SetMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasMessageValue = true;
         result.messageValue_ = value;
         return this;
@@ -2139,6 +2360,7 @@ namespace UnitTest.Issues.TestProtos {
       [global::System.ObsoleteAttribute()]
       public Builder SetMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasMessageValue = true;
         result.messageValue_ = builderForValue.Build();
         return this;
@@ -2146,6 +2368,7 @@ namespace UnitTest.Issues.TestProtos {
       [global::System.ObsoleteAttribute()]
       public Builder MergeMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasMessageValue &&
             result.messageValue_ != global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance) {
             result.messageValue_ = global::UnitTest.Issues.TestProtos.DeprecatedChild.CreateBuilder(result.messageValue_).MergeFrom(value).BuildPartial();
@@ -2157,6 +2380,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       [global::System.ObsoleteAttribute()]
       public Builder ClearMessageValue() {
+        PrepareBuilder();
         result.hasMessageValue = false;
         result.messageValue_ = global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance;
         return this;
@@ -2164,7 +2388,7 @@ namespace UnitTest.Issues.TestProtos {
       
       [global::System.ObsoleteAttribute()]
       public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArrayList {
-        get { return result.messageArray_; }
+        get { return PrepareBuilder().messageArray_; }
       }
       [global::System.ObsoleteAttribute()]
       public int MessageArrayCount {
@@ -2177,34 +2401,40 @@ namespace UnitTest.Issues.TestProtos {
       [global::System.ObsoleteAttribute()]
       public Builder SetMessageArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.messageArray_[index] = value;
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder SetMessageArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.messageArray_[index] = builderForValue.Build();
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder AddMessageArray(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.messageArray_.Add(value);
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder AddMessageArray(global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.messageArray_.Add(builderForValue.Build());
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder AddRangeMessageArray(scg::IEnumerable<global::UnitTest.Issues.TestProtos.DeprecatedChild> values) {
+        PrepareBuilder();
         result.messageArray_.Add(values);
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder ClearMessageArray() {
+        PrepareBuilder();
         result.messageArray_.Clear();
         return this;
       }
@@ -2220,12 +2450,14 @@ namespace UnitTest.Issues.TestProtos {
       }
       [global::System.ObsoleteAttribute()]
       public Builder SetEnumValue(global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
+        PrepareBuilder();
         result.hasEnumValue = true;
         result.enumValue_ = value;
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder ClearEnumValue() {
+        PrepareBuilder();
         result.hasEnumValue = false;
         result.enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.one;
         return this;
@@ -2233,7 +2465,7 @@ namespace UnitTest.Issues.TestProtos {
       
       [global::System.ObsoleteAttribute()]
       public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArrayList {
-        get { return result.enumArray_; }
+        get { return PrepareBuilder().enumArray_; }
       }
       [global::System.ObsoleteAttribute()]
       public int EnumArrayCount {
@@ -2245,21 +2477,25 @@ namespace UnitTest.Issues.TestProtos {
       }
       [global::System.ObsoleteAttribute()]
       public Builder SetEnumArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
+        PrepareBuilder();
         result.enumArray_[index] = value;
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder AddEnumArray(global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
+        PrepareBuilder();
         result.enumArray_.Add(value);
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder AddRangeEnumArray(scg::IEnumerable<global::UnitTest.Issues.TestProtos.DeprecatedEnum> values) {
+        PrepareBuilder();
         result.enumArray_.Add(values);
         return this;
       }
       [global::System.ObsoleteAttribute()]
       public Builder ClearEnumArray() {
+        PrepareBuilder();
         result.enumArray_.Clear();
         return this;
       }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 195 - 23
src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSizeProtoFile.cs


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 195 - 23
src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSpeedProtoFile.cs


+ 41 - 11
src/ProtocolBuffers.Test/TestProtos/UnitTestImportLiteProtoFile.cs

@@ -151,7 +151,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(ImportMessageLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -161,21 +161,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new ImportMessageLite();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(ImportMessageLite cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      ImportMessageLite result;
       
-      ImportMessageLite result = new ImportMessageLite();
+      private ImportMessageLite PrepareBuilder() {
+        if (builderIsReadOnly) {
+          ImportMessageLite original = result;
+          result = new ImportMessageLite();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessageLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessageLite();
+        result = DefaultInstance ?? new ImportMessageLite();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override ImportMessageLite DefaultInstanceForType {
@@ -183,12 +210,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessageLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        ImportMessageLite returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -202,6 +228,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessageLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessageLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -213,6 +240,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -255,11 +283,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 41 - 11
src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs

@@ -170,7 +170,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(ImportMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -180,21 +180,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new ImportMessage();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(ImportMessage cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      ImportMessage result;
       
-      ImportMessage result = new ImportMessage();
+      private ImportMessage PrepareBuilder() {
+        if (builderIsReadOnly) {
+          ImportMessage original = result;
+          result = new ImportMessage();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessage();
+        result = DefaultInstance ?? new ImportMessage();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -206,12 +233,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        ImportMessage returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -225,6 +251,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -237,6 +264,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -292,11 +320,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 253 - 67
src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs

@@ -190,7 +190,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestMessageSet prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -200,21 +200,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestMessageSet();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestMessageSet cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestMessageSet result = new TestMessageSet();
+      bool builderIsReadOnly;
+      TestMessageSet result;
+      
+      private TestMessageSet PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestMessageSet original = result;
+          result = new TestMessageSet();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSet MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSet();
+        result = DefaultInstance ?? new TestMessageSet();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -226,12 +253,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSet BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestMessageSet returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -245,6 +271,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSet other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance) return this;
+        PrepareBuilder();
           this.MergeExtensionFields(other);
         this.MergeUnknownFields(other.UnknownFields);
         return this;
@@ -255,6 +282,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -406,7 +434,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestMessageSetContainer prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -416,21 +444,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestMessageSetContainer();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestMessageSetContainer cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestMessageSetContainer result = new TestMessageSetContainer();
+      bool builderIsReadOnly;
+      TestMessageSetContainer result;
+      
+      private TestMessageSetContainer PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestMessageSetContainer original = result;
+          result = new TestMessageSetContainer();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSetContainer MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSetContainer();
+        result = DefaultInstance ?? new TestMessageSetContainer();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -442,12 +497,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSetContainer BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestMessageSetContainer returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -461,6 +515,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSetContainer other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSetContainer.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasMessageSet) {
           MergeMessageSet(other.MessageSet);
         }
@@ -473,6 +528,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -534,18 +590,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetMessageSet(global::Google.ProtocolBuffers.TestProtos.TestMessageSet value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasMessageSet = true;
         result.messageSet_ = value;
         return this;
       }
       public Builder SetMessageSet(global::Google.ProtocolBuffers.TestProtos.TestMessageSet.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasMessageSet = true;
         result.messageSet_ = builderForValue.Build();
         return this;
       }
       public Builder MergeMessageSet(global::Google.ProtocolBuffers.TestProtos.TestMessageSet value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasMessageSet &&
             result.messageSet_ != global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance) {
             result.messageSet_ = global::Google.ProtocolBuffers.TestProtos.TestMessageSet.CreateBuilder(result.messageSet_).MergeFrom(value).BuildPartial();
@@ -556,6 +615,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMessageSet() {
+        PrepareBuilder();
         result.hasMessageSet = false;
         result.messageSet_ = global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance;
         return this;
@@ -671,7 +731,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestMessageSetExtension1 prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -681,21 +741,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestMessageSetExtension1();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestMessageSetExtension1 cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestMessageSetExtension1 result = new TestMessageSetExtension1();
+      bool builderIsReadOnly;
+      TestMessageSetExtension1 result;
+      
+      private TestMessageSetExtension1 PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestMessageSetExtension1 original = result;
+          result = new TestMessageSetExtension1();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSetExtension1 MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSetExtension1();
+        result = DefaultInstance ?? new TestMessageSetExtension1();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -707,12 +794,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSetExtension1 BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestMessageSetExtension1 returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -726,6 +812,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSetExtension1 other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSetExtension1.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasI) {
           I = other.I;
         }
@@ -738,6 +825,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -793,11 +881,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetI(value); }
       }
       public Builder SetI(int value) {
+        PrepareBuilder();
         result.hasI = true;
         result.i_ = value;
         return this;
       }
       public Builder ClearI() {
+        PrepareBuilder();
         result.hasI = false;
         result.i_ = 0;
         return this;
@@ -913,7 +1003,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestMessageSetExtension2 prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -923,21 +1013,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestMessageSetExtension2();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestMessageSetExtension2 cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestMessageSetExtension2 result = new TestMessageSetExtension2();
+      bool builderIsReadOnly;
+      TestMessageSetExtension2 result;
+      
+      private TestMessageSetExtension2 PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestMessageSetExtension2 original = result;
+          result = new TestMessageSetExtension2();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessageSetExtension2 MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessageSetExtension2();
+        result = DefaultInstance ?? new TestMessageSetExtension2();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -949,12 +1066,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestMessageSetExtension2 BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestMessageSetExtension2 returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -968,6 +1084,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestMessageSetExtension2 other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageSetExtension2.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasStr) {
           Str = other.Str;
         }
@@ -980,6 +1097,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1036,11 +1154,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetStr(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasStr = true;
         result.str_ = value;
         return this;
       }
       public Builder ClearStr() {
+        PrepareBuilder();
         result.hasStr = false;
         result.str_ = "";
         return this;
@@ -1205,7 +1325,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         public override Builder ToBuilder() { return CreateBuilder(this); }
         public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(Item prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1215,21 +1335,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance ?? new Item();
+            builderIsReadOnly = result == DefaultInstance;
+          }
+          internal Builder(Item cloneFrom) {
+            result = cloneFrom;
+            builderIsReadOnly = true;
+          }
           
-          Item result = new Item();
+          bool builderIsReadOnly;
+          Item result;
+          
+          private Item PrepareBuilder() {
+            if (builderIsReadOnly) {
+              Item original = result;
+              result = new Item();
+              builderIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override Item MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new Item();
+            result = DefaultInstance ?? new Item();
+            builderIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (builderIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override pbd::MessageDescriptor DescriptorForType {
@@ -1241,12 +1388,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Item BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (builderIsReadOnly) {
+              return result;
             }
-            Item returnMe = result;
-            result = null;
-            return returnMe;
+            builderIsReadOnly = true;
+            return result;
           }
           
           public override Builder MergeFrom(pb::IMessage other) {
@@ -1260,6 +1406,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(Item other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasTypeId) {
               TypeId = other.TypeId;
             }
@@ -1275,6 +1422,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             pb::UnknownFieldSet.Builder unknownFields = null;
             uint tag;
             string field_name;
@@ -1334,11 +1482,13 @@ namespace Google.ProtocolBuffers.TestProtos {
             set { SetTypeId(value); }
           }
           public Builder SetTypeId(int value) {
+            PrepareBuilder();
             result.hasTypeId = true;
             result.typeId_ = value;
             return this;
           }
           public Builder ClearTypeId() {
+            PrepareBuilder();
             result.hasTypeId = false;
             result.typeId_ = 0;
             return this;
@@ -1353,11 +1503,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetMessage(pb::ByteString value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasMessage = true;
             result.message_ = value;
             return this;
           }
           public Builder ClearMessage() {
+            PrepareBuilder();
             result.hasMessage = false;
             result.message_ = pb::ByteString.Empty;
             return this;
@@ -1448,7 +1600,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(RawMessageSet prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1458,21 +1610,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new RawMessageSet();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(RawMessageSet cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      RawMessageSet result = new RawMessageSet();
+      bool builderIsReadOnly;
+      RawMessageSet result;
+      
+      private RawMessageSet PrepareBuilder() {
+        if (builderIsReadOnly) {
+          RawMessageSet original = result;
+          result = new RawMessageSet();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override RawMessageSet MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new RawMessageSet();
+        result = DefaultInstance ?? new RawMessageSet();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1484,13 +1663,12 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override RawMessageSet BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.item_.MakeReadOnly();
-        RawMessageSet returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1504,6 +1682,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(RawMessageSet other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.RawMessageSet.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.item_.Count != 0) {
           result.item_.Add(other.item_);
         }
@@ -1516,6 +1695,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1564,7 +1744,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> ItemList {
-        get { return result.item_; }
+        get { return PrepareBuilder().item_; }
       }
       public int ItemCount {
         get { return result.ItemCount; }
@@ -1574,29 +1754,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetItem(int index, global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.item_[index] = value;
         return this;
       }
       public Builder SetItem(int index, global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.item_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddItem(global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.item_.Add(value);
         return this;
       }
       public Builder AddItem(global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.item_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeItem(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> values) {
+        PrepareBuilder();
         result.item_.Add(values);
         return this;
       }
       public Builder ClearItem() {
+        PrepareBuilder();
         result.item_.Clear();
         return this;
       }

+ 41 - 11
src/ProtocolBuffers.Test/TestProtos/UnitTestNoGenericServicesProtoFile.cs

@@ -184,7 +184,7 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -194,21 +194,48 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestMessage();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestMessage cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      TestMessage result;
       
-      TestMessage result = new TestMessage();
+      private TestMessage PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestMessage original = result;
+          result = new TestMessage();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestMessage();
+        result = DefaultInstance ?? new TestMessage();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -220,12 +247,11 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       }
       
       public override TestMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestMessage returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -239,6 +265,7 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       
       public override Builder MergeFrom(TestMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.NoGenericService.TestMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasA) {
           A = other.A;
         }
@@ -252,6 +279,7 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -307,11 +335,13 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
         set { SetA(value); }
       }
       public Builder SetA(int value) {
+        PrepareBuilder();
         result.hasA = true;
         result.a_ = value;
         return this;
       }
       public Builder ClearA() {
+        PrepareBuilder();
         result.hasA = false;
         result.a_ = 0;
         return this;

+ 123 - 33
src/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs

@@ -165,7 +165,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -175,21 +175,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestOptimizedForSize();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestOptimizedForSize result = new TestOptimizedForSize();
+      bool builderIsReadOnly;
+      TestOptimizedForSize result;
+      
+      private TestOptimizedForSize PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestOptimizedForSize original = result;
+          result = new TestOptimizedForSize();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestOptimizedForSize();
+        result = DefaultInstance ?? new TestOptimizedForSize();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -201,12 +228,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       
@@ -218,11 +244,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetI(value); }
       }
       public Builder SetI(int value) {
+        PrepareBuilder();
         result.hasI = true;
         result.i_ = value;
         return this;
       }
       public Builder ClearI() {
+        PrepareBuilder();
         result.hasI = false;
         result.i_ = 0;
         return this;
@@ -237,18 +265,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasMsg = true;
         result.msg_ = value;
         return this;
       }
       public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasMsg = true;
         result.msg_ = builderForValue.Build();
         return this;
       }
       public Builder MergeMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasMsg &&
             result.msg_ != global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance) {
             result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.CreateBuilder(result.msg_).MergeFrom(value).BuildPartial();
@@ -259,6 +290,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMsg() {
+        PrepareBuilder();
         result.hasMsg = false;
         result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance;
         return this;
@@ -339,7 +371,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestRequiredOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -349,21 +381,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestRequiredOptimizedForSize();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestRequiredOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestRequiredOptimizedForSize result = new TestRequiredOptimizedForSize();
+      bool builderIsReadOnly;
+      TestRequiredOptimizedForSize result;
+      
+      private TestRequiredOptimizedForSize PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestRequiredOptimizedForSize original = result;
+          result = new TestRequiredOptimizedForSize();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestRequiredOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestRequiredOptimizedForSize();
+        result = DefaultInstance ?? new TestRequiredOptimizedForSize();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -375,12 +434,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestRequiredOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestRequiredOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       
@@ -392,11 +450,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetX(value); }
       }
       public Builder SetX(int value) {
+        PrepareBuilder();
         result.hasX = true;
         result.x_ = value;
         return this;
       }
       public Builder ClearX() {
+        PrepareBuilder();
         result.hasX = false;
         result.x_ = 0;
         return this;
@@ -477,7 +537,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestOptionalOptimizedForSize prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -487,21 +547,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestOptionalOptimizedForSize();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestOptionalOptimizedForSize cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestOptionalOptimizedForSize result = new TestOptionalOptimizedForSize();
+      bool builderIsReadOnly;
+      TestOptionalOptimizedForSize result;
+      
+      private TestOptionalOptimizedForSize PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestOptionalOptimizedForSize original = result;
+          result = new TestOptionalOptimizedForSize();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestOptionalOptimizedForSize MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestOptionalOptimizedForSize();
+        result = DefaultInstance ?? new TestOptionalOptimizedForSize();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -513,12 +600,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestOptionalOptimizedForSize BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestOptionalOptimizedForSize returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       
@@ -531,18 +617,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasO = true;
         result.o_ = value;
         return this;
       }
       public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasO = true;
         result.o_ = builderForValue.Build();
         return this;
       }
       public Builder MergeO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasO &&
             result.o_ != global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance) {
             result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.CreateBuilder(result.o_).MergeFrom(value).BuildPartial();
@@ -553,6 +642,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearO() {
+        PrepareBuilder();
         result.hasO = false;
         result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance;
         return this;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 249 - 51
src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs


+ 181 - 47
src/ProtocolBuffers.Test/TestProtos/UnitTestRpcInterop.cs

@@ -189,7 +189,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(SearchRequest prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -199,21 +199,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new SearchRequest();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(SearchRequest cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      SearchRequest result;
       
-      SearchRequest result = new SearchRequest();
+      private SearchRequest PrepareBuilder() {
+        if (builderIsReadOnly) {
+          SearchRequest original = result;
+          result = new SearchRequest();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override SearchRequest MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new SearchRequest();
+        result = DefaultInstance ?? new SearchRequest();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -225,13 +252,12 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override SearchRequest BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.criteria_.MakeReadOnly();
-        SearchRequest returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -245,6 +271,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(SearchRequest other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.SearchRequest.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.criteria_.Count != 0) {
           result.criteria_.Add(other.criteria_);
         }
@@ -257,6 +284,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -305,7 +333,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<string> CriteriaList {
-        get { return result.criteria_; }
+        get { return PrepareBuilder().criteria_; }
       }
       public int CriteriaCount {
         get { return result.CriteriaCount; }
@@ -315,19 +343,23 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetCriteria(int index, string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.criteria_[index] = value;
         return this;
       }
       public Builder AddCriteria(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.criteria_.Add(value);
         return this;
       }
       public Builder AddRangeCriteria(scg::IEnumerable<string> values) {
+        PrepareBuilder();
         result.criteria_.Add(values);
         return this;
       }
       public Builder ClearCriteria() {
+        PrepareBuilder();
         result.criteria_.Clear();
         return this;
       }
@@ -490,7 +522,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         public override Builder ToBuilder() { return CreateBuilder(this); }
         public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(ResultItem prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -500,21 +532,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance ?? new ResultItem();
+            builderIsReadOnly = result == DefaultInstance;
+          }
+          internal Builder(ResultItem cloneFrom) {
+            result = cloneFrom;
+            builderIsReadOnly = true;
+          }
+          
+          bool builderIsReadOnly;
+          ResultItem result;
           
-          ResultItem result = new ResultItem();
+          private ResultItem PrepareBuilder() {
+            if (builderIsReadOnly) {
+              ResultItem original = result;
+              result = new ResultItem();
+              builderIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override ResultItem MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new ResultItem();
+            result = DefaultInstance ?? new ResultItem();
+            builderIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (builderIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override pbd::MessageDescriptor DescriptorForType {
@@ -526,12 +585,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override ResultItem BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (builderIsReadOnly) {
+              return result;
             }
-            ResultItem returnMe = result;
-            result = null;
-            return returnMe;
+            builderIsReadOnly = true;
+            return result;
           }
           
           public override Builder MergeFrom(pb::IMessage other) {
@@ -545,6 +603,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(ResultItem other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasUrl) {
               Url = other.Url;
             }
@@ -560,6 +619,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             pb::UnknownFieldSet.Builder unknownFields = null;
             uint tag;
             string field_name;
@@ -620,11 +680,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetUrl(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasUrl = true;
             result.url_ = value;
             return this;
           }
           public Builder ClearUrl() {
+            PrepareBuilder();
             result.hasUrl = false;
             result.url_ = "";
             return this;
@@ -639,11 +701,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetName(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasName = true;
             result.name_ = value;
             return this;
           }
           public Builder ClearName() {
+            PrepareBuilder();
             result.hasName = false;
             result.name_ = "";
             return this;
@@ -737,7 +801,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(SearchResponse prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -747,21 +811,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new SearchResponse();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(SearchResponse cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      SearchResponse result;
       
-      SearchResponse result = new SearchResponse();
+      private SearchResponse PrepareBuilder() {
+        if (builderIsReadOnly) {
+          SearchResponse original = result;
+          result = new SearchResponse();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override SearchResponse MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new SearchResponse();
+        result = DefaultInstance ?? new SearchResponse();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -773,13 +864,12 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override SearchResponse BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.results_.MakeReadOnly();
-        SearchResponse returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -793,6 +883,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(SearchResponse other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.results_.Count != 0) {
           result.results_.Add(other.results_);
         }
@@ -805,6 +896,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -853,7 +945,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> ResultsList {
-        get { return result.results_; }
+        get { return PrepareBuilder().results_; }
       }
       public int ResultsCount {
         get { return result.ResultsCount; }
@@ -863,29 +955,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetResults(int index, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.results_[index] = value;
         return this;
       }
       public Builder SetResults(int index, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.results_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.results_.Add(value);
         return this;
       }
       public Builder AddResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.results_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeResults(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem> values) {
+        PrepareBuilder();
         result.results_.Add(values);
         return this;
       }
       public Builder ClearResults() {
+        PrepareBuilder();
         result.results_.Clear();
         return this;
       }
@@ -1023,7 +1121,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(RefineSearchRequest prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1033,21 +1131,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new RefineSearchRequest();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(RefineSearchRequest cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      RefineSearchRequest result;
       
-      RefineSearchRequest result = new RefineSearchRequest();
+      private RefineSearchRequest PrepareBuilder() {
+        if (builderIsReadOnly) {
+          RefineSearchRequest original = result;
+          result = new RefineSearchRequest();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override RefineSearchRequest MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new RefineSearchRequest();
+        result = DefaultInstance ?? new RefineSearchRequest();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1059,13 +1184,12 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override RefineSearchRequest BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.criteria_.MakeReadOnly();
-        RefineSearchRequest returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1079,6 +1203,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(RefineSearchRequest other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.RefineSearchRequest.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.criteria_.Count != 0) {
           result.criteria_.Add(other.criteria_);
         }
@@ -1094,6 +1219,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1151,7 +1277,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<string> CriteriaList {
-        get { return result.criteria_; }
+        get { return PrepareBuilder().criteria_; }
       }
       public int CriteriaCount {
         get { return result.CriteriaCount; }
@@ -1161,19 +1287,23 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetCriteria(int index, string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.criteria_[index] = value;
         return this;
       }
       public Builder AddCriteria(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.criteria_.Add(value);
         return this;
       }
       public Builder AddRangeCriteria(scg::IEnumerable<string> values) {
+        PrepareBuilder();
         result.criteria_.Add(values);
         return this;
       }
       public Builder ClearCriteria() {
+        PrepareBuilder();
         result.criteria_.Clear();
         return this;
       }
@@ -1187,18 +1317,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetPreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasPreviousResults = true;
         result.previousResults_ = value;
         return this;
       }
       public Builder SetPreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasPreviousResults = true;
         result.previousResults_ = builderForValue.Build();
         return this;
       }
       public Builder MergePreviousResults(global::Google.ProtocolBuffers.TestProtos.SearchResponse value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasPreviousResults &&
             result.previousResults_ != global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance) {
             result.previousResults_ = global::Google.ProtocolBuffers.TestProtos.SearchResponse.CreateBuilder(result.previousResults_).MergeFrom(value).BuildPartial();
@@ -1209,6 +1342,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearPreviousResults() {
+        PrepareBuilder();
         result.hasPreviousResults = false;
         result.previousResults_ = global::Google.ProtocolBuffers.TestProtos.SearchResponse.DefaultInstance;
         return this;

+ 281 - 71
src/ProtocolBuffers.Test/TestProtos/UnitTestXmlSerializerTestProtoFile.cs

@@ -263,7 +263,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestXmlChild prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -274,21 +274,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestXmlChild();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestXmlChild cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestXmlChild result = new TestXmlChild();
+      bool builderIsReadOnly;
+      TestXmlChild result;
+      
+      private TestXmlChild PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestXmlChild original = result;
+          result = new TestXmlChild();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestXmlChild MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestXmlChild();
+        result = DefaultInstance ?? new TestXmlChild();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -300,13 +327,12 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestXmlChild BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.options_.MakeReadOnly();
-        TestXmlChild returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -320,6 +346,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestXmlChild other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.options_.Count != 0) {
           result.options_.Add(other.options_);
         }
@@ -335,6 +362,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -397,7 +425,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> OptionsList {
-        get { return result.options_; }
+        get { return PrepareBuilder().options_; }
       }
       public int OptionsCount {
         get { return result.OptionsCount; }
@@ -406,18 +434,22 @@ namespace Google.ProtocolBuffers.TestProtos {
         return result.GetOptions(index);
       }
       public Builder SetOptions(int index, global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
+        PrepareBuilder();
         result.options_[index] = value;
         return this;
       }
       public Builder AddOptions(global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
+        PrepareBuilder();
         result.options_.Add(value);
         return this;
       }
       public Builder AddRangeOptions(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.EnumOptions> values) {
+        PrepareBuilder();
         result.options_.Add(values);
         return this;
       }
       public Builder ClearOptions() {
+        PrepareBuilder();
         result.options_.Clear();
         return this;
       }
@@ -431,11 +463,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetBinary(pb::ByteString value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasBinary = true;
         result.binary_ = value;
         return this;
       }
       public Builder ClearBinary() {
+        PrepareBuilder();
         result.hasBinary = false;
         result.binary_ = pb::ByteString.Empty;
         return this;
@@ -534,7 +568,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestXmlNoFields prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -545,21 +579,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestXmlNoFields();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestXmlNoFields cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestXmlNoFields result = new TestXmlNoFields();
+      bool builderIsReadOnly;
+      TestXmlNoFields result;
+      
+      private TestXmlNoFields PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestXmlNoFields original = result;
+          result = new TestXmlNoFields();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestXmlNoFields MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestXmlNoFields();
+        result = DefaultInstance ?? new TestXmlNoFields();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -571,12 +632,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestXmlNoFields BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestXmlNoFields returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -590,6 +650,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestXmlNoFields other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.DefaultInstance) return this;
+        PrepareBuilder();
         this.MergeUnknownFields(other.UnknownFields);
         return this;
       }
@@ -599,6 +660,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -751,7 +813,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestXmlRescursive prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -762,21 +824,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestXmlRescursive();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestXmlRescursive cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestXmlRescursive result = new TestXmlRescursive();
+      bool builderIsReadOnly;
+      TestXmlRescursive result;
+      
+      private TestXmlRescursive PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestXmlRescursive original = result;
+          result = new TestXmlRescursive();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestXmlRescursive MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestXmlRescursive();
+        result = DefaultInstance ?? new TestXmlRescursive();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -788,12 +877,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestXmlRescursive BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestXmlRescursive returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -807,6 +895,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestXmlRescursive other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasChild) {
           MergeChild(other.Child);
         }
@@ -819,6 +908,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -880,18 +970,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasChild = true;
         result.child_ = value;
         return this;
       }
       public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasChild = true;
         result.child_ = builderForValue.Build();
         return this;
       }
       public Builder MergeChild(global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasChild &&
             result.child_ != global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance) {
             result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.CreateBuilder(result.child_).MergeFrom(value).BuildPartial();
@@ -902,6 +995,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearChild() {
+        PrepareBuilder();
         result.hasChild = false;
         result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance;
         return this;
@@ -1075,7 +1169,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         public override Builder ToBuilder() { return CreateBuilder(this); }
         public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(Children prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.SerializableAttribute()]
@@ -1086,21 +1180,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance ?? new Children();
+            builderIsReadOnly = result == DefaultInstance;
+          }
+          internal Builder(Children cloneFrom) {
+            result = cloneFrom;
+            builderIsReadOnly = true;
+          }
           
-          Children result = new Children();
+          bool builderIsReadOnly;
+          Children result;
+          
+          private Children PrepareBuilder() {
+            if (builderIsReadOnly) {
+              Children original = result;
+              result = new Children();
+              builderIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override Children MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new Children();
+            result = DefaultInstance ?? new Children();
+            builderIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (builderIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override pbd::MessageDescriptor DescriptorForType {
@@ -1112,13 +1233,12 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Children BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (builderIsReadOnly) {
+              return result;
             }
             result.options_.MakeReadOnly();
-            Children returnMe = result;
-            result = null;
-            return returnMe;
+            builderIsReadOnly = true;
+            return result;
           }
           
           public override Builder MergeFrom(pb::IMessage other) {
@@ -1132,6 +1252,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(Children other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.options_.Count != 0) {
               result.options_.Add(other.options_);
             }
@@ -1147,6 +1268,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             pb::UnknownFieldSet.Builder unknownFields = null;
             uint tag;
             string field_name;
@@ -1209,7 +1331,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           
           public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> OptionsList {
-            get { return result.options_; }
+            get { return PrepareBuilder().options_; }
           }
           public int OptionsCount {
             get { return result.OptionsCount; }
@@ -1218,18 +1340,22 @@ namespace Google.ProtocolBuffers.TestProtos {
             return result.GetOptions(index);
           }
           public Builder SetOptions(int index, global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
+            PrepareBuilder();
             result.options_[index] = value;
             return this;
           }
           public Builder AddOptions(global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
+            PrepareBuilder();
             result.options_.Add(value);
             return this;
           }
           public Builder AddRangeOptions(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.EnumOptions> values) {
+            PrepareBuilder();
             result.options_.Add(values);
             return this;
           }
           public Builder ClearOptions() {
+            PrepareBuilder();
             result.options_.Clear();
             return this;
           }
@@ -1243,11 +1369,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetBinary(pb::ByteString value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasBinary = true;
             result.binary_ = value;
             return this;
           }
           public Builder ClearBinary() {
+            PrepareBuilder();
             result.hasBinary = false;
             result.binary_ = pb::ByteString.Empty;
             return this;
@@ -1452,7 +1580,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestXmlMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -1463,21 +1591,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestXmlMessage();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestXmlMessage cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestXmlMessage result = new TestXmlMessage();
+      bool builderIsReadOnly;
+      TestXmlMessage result;
+      
+      private TestXmlMessage PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestXmlMessage original = result;
+          result = new TestXmlMessage();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestXmlMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestXmlMessage();
+        result = DefaultInstance ?? new TestXmlMessage();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1489,15 +1644,14 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestXmlMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.numbers_.MakeReadOnly();
         result.textlines_.MakeReadOnly();
         result.children_.MakeReadOnly();
-        TestXmlMessage returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1511,6 +1665,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestXmlMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNumber) {
           Number = other.Number;
         }
@@ -1542,6 +1697,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1627,18 +1783,20 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetNumber(value); }
       }
       public Builder SetNumber(long value) {
+        PrepareBuilder();
         result.hasNumber = true;
         result.number_ = value;
         return this;
       }
       public Builder ClearNumber() {
+        PrepareBuilder();
         result.hasNumber = false;
         result.number_ = 0L;
         return this;
       }
       
       public pbc::IPopsicleList<int> NumbersList {
-        get { return result.numbers_; }
+        get { return PrepareBuilder().numbers_; }
       }
       public int NumbersCount {
         get { return result.NumbersCount; }
@@ -1647,18 +1805,22 @@ namespace Google.ProtocolBuffers.TestProtos {
         return result.GetNumbers(index);
       }
       public Builder SetNumbers(int index, int value) {
+        PrepareBuilder();
         result.numbers_[index] = value;
         return this;
       }
       public Builder AddNumbers(int value) {
+        PrepareBuilder();
         result.numbers_.Add(value);
         return this;
       }
       public Builder AddRangeNumbers(scg::IEnumerable<int> values) {
+        PrepareBuilder();
         result.numbers_.Add(values);
         return this;
       }
       public Builder ClearNumbers() {
+        PrepareBuilder();
         result.numbers_.Clear();
         return this;
       }
@@ -1672,18 +1834,20 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetText(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasText = true;
         result.text_ = value;
         return this;
       }
       public Builder ClearText() {
+        PrepareBuilder();
         result.hasText = false;
         result.text_ = "";
         return this;
       }
       
       public pbc::IPopsicleList<string> TextlinesList {
-        get { return result.textlines_; }
+        get { return PrepareBuilder().textlines_; }
       }
       public int TextlinesCount {
         get { return result.TextlinesCount; }
@@ -1693,19 +1857,23 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetTextlines(int index, string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.textlines_[index] = value;
         return this;
       }
       public Builder AddTextlines(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.textlines_.Add(value);
         return this;
       }
       public Builder AddRangeTextlines(scg::IEnumerable<string> values) {
+        PrepareBuilder();
         result.textlines_.Add(values);
         return this;
       }
       public Builder ClearTextlines() {
+        PrepareBuilder();
         result.textlines_.Clear();
         return this;
       }
@@ -1718,11 +1886,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetValid(value); }
       }
       public Builder SetValid(bool value) {
+        PrepareBuilder();
         result.hasValid = true;
         result.valid_ = value;
         return this;
       }
       public Builder ClearValid() {
+        PrepareBuilder();
         result.hasValid = false;
         result.valid_ = false;
         return this;
@@ -1737,18 +1907,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlChild value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasChild = true;
         result.child_ = value;
         return this;
       }
       public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlChild.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasChild = true;
         result.child_ = builderForValue.Build();
         return this;
       }
       public Builder MergeChild(global::Google.ProtocolBuffers.TestProtos.TestXmlChild value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasChild &&
             result.child_ != global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance) {
             result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlChild.CreateBuilder(result.child_).MergeFrom(value).BuildPartial();
@@ -1759,13 +1932,14 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearChild() {
+        PrepareBuilder();
         result.hasChild = false;
         result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance;
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children> ChildrenList {
-        get { return result.children_; }
+        get { return PrepareBuilder().children_; }
       }
       public int ChildrenCount {
         get { return result.ChildrenCount; }
@@ -1775,29 +1949,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetChildren(int index, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.children_[index] = value;
         return this;
       }
       public Builder SetChildren(int index, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.children_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddChildren(global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.children_.Add(value);
         return this;
       }
       public Builder AddChildren(global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.children_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeChildren(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children> values) {
+        PrepareBuilder();
         result.children_.Add(values);
         return this;
       }
       public Builder ClearChildren() {
+        PrepareBuilder();
         result.children_.Clear();
         return this;
       }
@@ -1912,7 +2092,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestXmlExtension prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -1923,21 +2103,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestXmlExtension();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestXmlExtension cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestXmlExtension result = new TestXmlExtension();
+      bool builderIsReadOnly;
+      TestXmlExtension result;
+      
+      private TestXmlExtension PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestXmlExtension original = result;
+          result = new TestXmlExtension();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestXmlExtension MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestXmlExtension();
+        result = DefaultInstance ?? new TestXmlExtension();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1949,12 +2156,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestXmlExtension BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestXmlExtension returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1968,6 +2174,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestXmlExtension other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlExtension.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNumber) {
           Number = other.Number;
         }
@@ -1980,6 +2187,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -2035,11 +2243,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetNumber(value); }
       }
       public Builder SetNumber(int value) {
+        PrepareBuilder();
         result.hasNumber = true;
         result.number_ = value;
         return this;
       }
       public Builder ClearNumber() {
+        PrepareBuilder();
         result.hasNumber = false;
         result.number_ = 0;
         return this;

+ 190 - 44
src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs

@@ -433,7 +433,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(CSharpFileOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -443,21 +443,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new CSharpFileOptions();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(CSharpFileOptions cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      CSharpFileOptions result;
       
-      CSharpFileOptions result = new CSharpFileOptions();
+      private CSharpFileOptions PrepareBuilder() {
+        if (builderIsReadOnly) {
+          CSharpFileOptions original = result;
+          result = new CSharpFileOptions();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpFileOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpFileOptions();
+        result = DefaultInstance ?? new CSharpFileOptions();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -469,12 +496,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpFileOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        CSharpFileOptions returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -488,6 +514,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpFileOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpFileOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNamespace) {
           Namespace = other.Namespace;
         }
@@ -539,6 +566,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -655,11 +683,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetNamespace(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasNamespace = true;
         result.namespace_ = value;
         return this;
       }
       public Builder ClearNamespace() {
+        PrepareBuilder();
         result.hasNamespace = false;
         result.namespace_ = "";
         return this;
@@ -674,11 +704,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetUmbrellaClassname(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasUmbrellaClassname = true;
         result.umbrellaClassname_ = value;
         return this;
       }
       public Builder ClearUmbrellaClassname() {
+        PrepareBuilder();
         result.hasUmbrellaClassname = false;
         result.umbrellaClassname_ = "";
         return this;
@@ -692,11 +724,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetPublicClasses(value); }
       }
       public Builder SetPublicClasses(bool value) {
+        PrepareBuilder();
         result.hasPublicClasses = true;
         result.publicClasses_ = value;
         return this;
       }
       public Builder ClearPublicClasses() {
+        PrepareBuilder();
         result.hasPublicClasses = false;
         result.publicClasses_ = true;
         return this;
@@ -710,11 +744,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetMultipleFiles(value); }
       }
       public Builder SetMultipleFiles(bool value) {
+        PrepareBuilder();
         result.hasMultipleFiles = true;
         result.multipleFiles_ = value;
         return this;
       }
       public Builder ClearMultipleFiles() {
+        PrepareBuilder();
         result.hasMultipleFiles = false;
         result.multipleFiles_ = false;
         return this;
@@ -728,11 +764,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetNestClasses(value); }
       }
       public Builder SetNestClasses(bool value) {
+        PrepareBuilder();
         result.hasNestClasses = true;
         result.nestClasses_ = value;
         return this;
       }
       public Builder ClearNestClasses() {
+        PrepareBuilder();
         result.hasNestClasses = false;
         result.nestClasses_ = false;
         return this;
@@ -746,11 +784,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetCodeContracts(value); }
       }
       public Builder SetCodeContracts(bool value) {
+        PrepareBuilder();
         result.hasCodeContracts = true;
         result.codeContracts_ = value;
         return this;
       }
       public Builder ClearCodeContracts() {
+        PrepareBuilder();
         result.hasCodeContracts = false;
         result.codeContracts_ = false;
         return this;
@@ -764,11 +804,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetExpandNamespaceDirectories(value); }
       }
       public Builder SetExpandNamespaceDirectories(bool value) {
+        PrepareBuilder();
         result.hasExpandNamespaceDirectories = true;
         result.expandNamespaceDirectories_ = value;
         return this;
       }
       public Builder ClearExpandNamespaceDirectories() {
+        PrepareBuilder();
         result.hasExpandNamespaceDirectories = false;
         result.expandNamespaceDirectories_ = false;
         return this;
@@ -782,11 +824,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetClsCompliance(value); }
       }
       public Builder SetClsCompliance(bool value) {
+        PrepareBuilder();
         result.hasClsCompliance = true;
         result.clsCompliance_ = value;
         return this;
       }
       public Builder ClearClsCompliance() {
+        PrepareBuilder();
         result.hasClsCompliance = false;
         result.clsCompliance_ = true;
         return this;
@@ -800,11 +844,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetAddSerializable(value); }
       }
       public Builder SetAddSerializable(bool value) {
+        PrepareBuilder();
         result.hasAddSerializable = true;
         result.addSerializable_ = value;
         return this;
       }
       public Builder ClearAddSerializable() {
+        PrepareBuilder();
         result.hasAddSerializable = false;
         result.addSerializable_ = false;
         return this;
@@ -819,11 +865,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetFileExtension(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasFileExtension = true;
         result.fileExtension_ = value;
         return this;
       }
       public Builder ClearFileExtension() {
+        PrepareBuilder();
         result.hasFileExtension = false;
         result.fileExtension_ = ".cs";
         return this;
@@ -838,11 +886,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetUmbrellaNamespace(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasUmbrellaNamespace = true;
         result.umbrellaNamespace_ = value;
         return this;
       }
       public Builder ClearUmbrellaNamespace() {
+        PrepareBuilder();
         result.hasUmbrellaNamespace = false;
         result.umbrellaNamespace_ = "";
         return this;
@@ -857,11 +907,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetOutputDirectory(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasOutputDirectory = true;
         result.outputDirectory_ = value;
         return this;
       }
       public Builder ClearOutputDirectory() {
+        PrepareBuilder();
         result.hasOutputDirectory = false;
         result.outputDirectory_ = ".";
         return this;
@@ -875,11 +927,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetIgnoreGoogleProtobuf(value); }
       }
       public Builder SetIgnoreGoogleProtobuf(bool value) {
+        PrepareBuilder();
         result.hasIgnoreGoogleProtobuf = true;
         result.ignoreGoogleProtobuf_ = value;
         return this;
       }
       public Builder ClearIgnoreGoogleProtobuf() {
+        PrepareBuilder();
         result.hasIgnoreGoogleProtobuf = false;
         result.ignoreGoogleProtobuf_ = false;
         return this;
@@ -893,11 +947,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetServiceGeneratorType(value); }
       }
       public Builder SetServiceGeneratorType(global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceType value) {
+        PrepareBuilder();
         result.hasServiceGeneratorType = true;
         result.serviceGeneratorType_ = value;
         return this;
       }
       public Builder ClearServiceGeneratorType() {
+        PrepareBuilder();
         result.hasServiceGeneratorType = false;
         result.serviceGeneratorType_ = global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceType.NONE;
         return this;
@@ -1011,7 +1067,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(CSharpFieldOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1021,21 +1077,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new CSharpFieldOptions();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(CSharpFieldOptions cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      CSharpFieldOptions result;
       
-      CSharpFieldOptions result = new CSharpFieldOptions();
+      private CSharpFieldOptions PrepareBuilder() {
+        if (builderIsReadOnly) {
+          CSharpFieldOptions original = result;
+          result = new CSharpFieldOptions();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpFieldOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpFieldOptions();
+        result = DefaultInstance ?? new CSharpFieldOptions();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1047,12 +1130,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpFieldOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        CSharpFieldOptions returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1066,6 +1148,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpFieldOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpFieldOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasPropertyName) {
           PropertyName = other.PropertyName;
         }
@@ -1078,6 +1161,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1134,11 +1218,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetPropertyName(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasPropertyName = true;
         result.propertyName_ = value;
         return this;
       }
       public Builder ClearPropertyName() {
+        PrepareBuilder();
         result.hasPropertyName = false;
         result.propertyName_ = "";
         return this;
@@ -1252,7 +1338,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(CSharpServiceOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1262,21 +1348,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new CSharpServiceOptions();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(CSharpServiceOptions cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      CSharpServiceOptions result;
       
-      CSharpServiceOptions result = new CSharpServiceOptions();
+      private CSharpServiceOptions PrepareBuilder() {
+        if (builderIsReadOnly) {
+          CSharpServiceOptions original = result;
+          result = new CSharpServiceOptions();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpServiceOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpServiceOptions();
+        result = DefaultInstance ?? new CSharpServiceOptions();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1288,12 +1401,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpServiceOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        CSharpServiceOptions returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1307,6 +1419,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpServiceOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasInterfaceId) {
           InterfaceId = other.InterfaceId;
         }
@@ -1319,6 +1432,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1375,11 +1489,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       public Builder SetInterfaceId(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasInterfaceId = true;
         result.interfaceId_ = value;
         return this;
       }
       public Builder ClearInterfaceId() {
+        PrepareBuilder();
         result.hasInterfaceId = false;
         result.interfaceId_ = "";
         return this;
@@ -1493,7 +1609,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(CSharpMethodOptions prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1503,21 +1619,48 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new CSharpMethodOptions();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(CSharpMethodOptions cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      CSharpMethodOptions result;
       
-      CSharpMethodOptions result = new CSharpMethodOptions();
+      private CSharpMethodOptions PrepareBuilder() {
+        if (builderIsReadOnly) {
+          CSharpMethodOptions original = result;
+          result = new CSharpMethodOptions();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override CSharpMethodOptions MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new CSharpMethodOptions();
+        result = DefaultInstance ?? new CSharpMethodOptions();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -1529,12 +1672,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override CSharpMethodOptions BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        CSharpMethodOptions returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -1548,6 +1690,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       public override Builder MergeFrom(CSharpMethodOptions other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.CSharpMethodOptions.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasDispatchId) {
           DispatchId = other.DispatchId;
         }
@@ -1560,6 +1703,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -1615,11 +1759,13 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         set { SetDispatchId(value); }
       }
       public Builder SetDispatchId(int value) {
+        PrepareBuilder();
         result.hasDispatchId = true;
         result.dispatchId_ = value;
         return this;
       }
       public Builder ClearDispatchId() {
+        PrepareBuilder();
         result.hasDispatchId = false;
         result.dispatchId_ = 0;
         return this;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 282 - 61
src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs


+ 3 - 8
src/ProtocolBuffers/GeneratedBuilder.cs

@@ -58,12 +58,7 @@ namespace Google.ProtocolBuffers
 
         protected internal FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors
         {
-            get { return MessageBeingBuilt.FieldAccessorsFromBuilder; }
-        }
-
-        public override bool IsInitialized
-        {
-            get { return MessageBeingBuilt.IsInitialized; }
+            get { return DefaultInstanceForType.FieldAccessorsFromBuilder; }
         }
 
         public override IDictionary<FieldDescriptor, object> AllFields
@@ -97,7 +92,7 @@ namespace Google.ProtocolBuffers
 
         public override MessageDescriptor DescriptorForType
         {
-            get { return MessageBeingBuilt.DescriptorForType; }
+            get { return DefaultInstanceForType.DescriptorForType; }
         }
 
         public override int GetRepeatedFieldCount(FieldDescriptor field)
@@ -204,7 +199,7 @@ namespace Google.ProtocolBuffers
         public override TMessage Build()
         {
             // If the message is null, we'll throw a more appropriate exception in BuildPartial.
-            if (MessageBeingBuilt != null && !IsInitialized)
+            if (!IsInitialized)
             {
                 throw new UninitializedMessageException(MessageBeingBuilt);
             }

+ 1 - 6
src/ProtocolBuffers/GeneratedBuilderLite.cs

@@ -61,11 +61,6 @@ namespace Google.ProtocolBuffers
 
         public abstract TBuilder MergeFrom(TMessage other);
 
-        public override bool IsInitialized
-        {
-            get { return MessageBeingBuilt.IsInitialized; }
-        }
-
         /// <summary>
         /// Called by derived classes to parse an unknown field.
         /// </summary>
@@ -96,7 +91,7 @@ namespace Google.ProtocolBuffers
         public override TMessage Build()
         {
             // If the message is null, we'll throw a more appropriate exception in BuildPartial.
-            if (MessageBeingBuilt != null && !IsInitialized)
+            if (!IsInitialized)
             {
                 throw new UninitializedMessageException(MessageBeingBuilt);
             }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 355 - 88
src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasFullProtoFile.cs


+ 240 - 58
src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasLiteProtoFile.cs

@@ -189,7 +189,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestRequiredLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -200,21 +200,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestRequiredLite();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestRequiredLite cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      TestRequiredLite result;
+      
+      private TestRequiredLite PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestRequiredLite original = result;
+          result = new TestRequiredLite();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
       
-      TestRequiredLite result = new TestRequiredLite();
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestRequiredLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestRequiredLite();
+        result = DefaultInstance ?? new TestRequiredLite();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestRequiredLite DefaultInstanceForType {
@@ -222,12 +249,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestRequiredLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestRequiredLite returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -241,6 +267,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestRequiredLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestRequiredLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -255,6 +282,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -305,11 +333,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;
@@ -323,11 +353,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetEn(value); }
       }
       public Builder SetEn(global::Google.ProtocolBuffers.TestProtos.ExtraEnum value) {
+        PrepareBuilder();
         result.hasEn = true;
         result.en_ = value;
         return this;
       }
       public Builder ClearEn() {
+        PrepareBuilder();
         result.hasEn = false;
         result.en_ = global::Google.ProtocolBuffers.TestProtos.ExtraEnum.DEFAULT;
         return this;
@@ -505,7 +537,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         public override Builder ToBuilder() { return CreateBuilder(this); }
         public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(PhoneNumber prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.SerializableAttribute()]
@@ -516,21 +548,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance ?? new PhoneNumber();
+            builderIsReadOnly = result == DefaultInstance;
+          }
+          internal Builder(PhoneNumber cloneFrom) {
+            result = cloneFrom;
+            builderIsReadOnly = true;
+          }
           
-          PhoneNumber result = new PhoneNumber();
+          bool builderIsReadOnly;
+          PhoneNumber result;
+          
+          private PhoneNumber PrepareBuilder() {
+            if (builderIsReadOnly) {
+              PhoneNumber original = result;
+              result = new PhoneNumber();
+              builderIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override PhoneNumber MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new PhoneNumber();
+            result = DefaultInstance ?? new PhoneNumber();
+            builderIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (builderIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override PhoneNumber DefaultInstanceForType {
@@ -538,12 +597,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override PhoneNumber BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (builderIsReadOnly) {
+              return result;
             }
-            PhoneNumber returnMe = result;
-            result = null;
-            return returnMe;
+            builderIsReadOnly = true;
+            return result;
           }
           
           public override Builder MergeFrom(pb::IMessageLite other) {
@@ -557,6 +615,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(PhoneNumber other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasNumber) {
               Number = other.Number;
             }
@@ -571,6 +630,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             uint tag;
             string field_name;
             while (input.ReadTag(out tag, out field_name)) {
@@ -622,11 +682,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetNumber(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasNumber = true;
             result.number_ = value;
             return this;
           }
           public Builder ClearNumber() {
+            PrepareBuilder();
             result.hasNumber = false;
             result.number_ = "";
             return this;
@@ -640,11 +702,13 @@ namespace Google.ProtocolBuffers.TestProtos {
             set { SetType(value); }
           }
           public Builder SetType(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType value) {
+            PrepareBuilder();
             result.hasType = true;
             result.type_ = value;
             return this;
           }
           public Builder ClearType() {
+            PrepareBuilder();
             result.hasType = false;
             result.type_ = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType.HOME;
             return this;
@@ -849,7 +913,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         public override Builder ToBuilder() { return CreateBuilder(this); }
         public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(Addresses prototype) {
-          return (Builder) new Builder().MergeFrom(prototype);
+          return new Builder(prototype);
         }
         
         [global::System.SerializableAttribute()]
@@ -860,21 +924,48 @@ namespace Google.ProtocolBuffers.TestProtos {
           protected override Builder ThisBuilder {
             get { return this; }
           }
-          public Builder() {}
+          public Builder() {
+            result = DefaultInstance ?? new Addresses();
+            builderIsReadOnly = result == DefaultInstance;
+          }
+          internal Builder(Addresses cloneFrom) {
+            result = cloneFrom;
+            builderIsReadOnly = true;
+          }
+          
+          bool builderIsReadOnly;
+          Addresses result;
           
-          Addresses result = new Addresses();
+          private Addresses PrepareBuilder() {
+            if (builderIsReadOnly) {
+              Addresses original = result;
+              result = new Addresses();
+              builderIsReadOnly = false;
+              MergeFrom(original);
+            }
+            return result;
+          }
+          
+          public override bool IsInitialized {
+            get { return result.IsInitialized; }
+          }
           
           protected override Addresses MessageBeingBuilt {
-            get { return result; }
+            get { return PrepareBuilder(); }
           }
           
           public override Builder Clear() {
-            result = new Addresses();
+            result = DefaultInstance ?? new Addresses();
+            builderIsReadOnly = true;
             return this;
           }
           
           public override Builder Clone() {
-            return new Builder().MergeFrom(result);
+            if (builderIsReadOnly) {
+              return new Builder(result);
+            } else {
+              return new Builder().MergeFrom(result);
+            }
           }
           
           public override Addresses DefaultInstanceForType {
@@ -882,12 +973,11 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Addresses BuildPartial() {
-            if (result == null) {
-              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+            if (builderIsReadOnly) {
+              return result;
             }
-            Addresses returnMe = result;
-            result = null;
-            return returnMe;
+            builderIsReadOnly = true;
+            return result;
           }
           
           public override Builder MergeFrom(pb::IMessageLite other) {
@@ -901,6 +991,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           
           public override Builder MergeFrom(Addresses other) {
             if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.DefaultInstance) return this;
+            PrepareBuilder();
             if (other.HasAddress) {
               Address = other.Address;
             }
@@ -924,6 +1015,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           
           public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+            PrepareBuilder();
             uint tag;
             string field_name;
             while (input.ReadTag(out tag, out field_name)) {
@@ -983,11 +1075,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetAddress(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasAddress = true;
             result.address_ = value;
             return this;
           }
           public Builder ClearAddress() {
+            PrepareBuilder();
             result.hasAddress = false;
             result.address_ = "";
             return this;
@@ -1002,11 +1096,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetAddress2(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasAddress2 = true;
             result.address2_ = value;
             return this;
           }
           public Builder ClearAddress2() {
+            PrepareBuilder();
             result.hasAddress2 = false;
             result.address2_ = "";
             return this;
@@ -1021,11 +1117,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetCity(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasCity = true;
             result.city_ = value;
             return this;
           }
           public Builder ClearCity() {
+            PrepareBuilder();
             result.hasCity = false;
             result.city_ = "";
             return this;
@@ -1040,11 +1138,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           public Builder SetState(string value) {
             pb::ThrowHelper.ThrowIfNull(value, "value");
+            PrepareBuilder();
             result.hasState = true;
             result.state_ = value;
             return this;
           }
           public Builder ClearState() {
+            PrepareBuilder();
             result.hasState = false;
             result.state_ = "";
             return this;
@@ -1060,11 +1160,13 @@ namespace Google.ProtocolBuffers.TestProtos {
           }
           [global::System.CLSCompliant(false)]
           public Builder SetZip(uint value) {
+            PrepareBuilder();
             result.hasZip = true;
             result.zip_ = value;
             return this;
           }
           public Builder ClearZip() {
+            PrepareBuilder();
             result.hasZip = false;
             result.zip_ = 0;
             return this;
@@ -1301,7 +1403,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestInteropPersonLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -1312,21 +1414,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestInteropPersonLite();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestInteropPersonLite cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestInteropPersonLite result = new TestInteropPersonLite();
+      bool builderIsReadOnly;
+      TestInteropPersonLite result;
+      
+      private TestInteropPersonLite PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestInteropPersonLite original = result;
+          result = new TestInteropPersonLite();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestInteropPersonLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestInteropPersonLite();
+        result = DefaultInstance ?? new TestInteropPersonLite();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestInteropPersonLite DefaultInstanceForType {
@@ -1334,15 +1463,14 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestInteropPersonLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
         result.codes_.MakeReadOnly();
         result.phone_.MakeReadOnly();
         result.addresses_.MakeReadOnly();
-        TestInteropPersonLite returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -1356,6 +1484,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestInteropPersonLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasName) {
           Name = other.Name;
         }
@@ -1383,6 +1512,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -1447,11 +1577,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetName(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasName = true;
         result.name_ = value;
         return this;
       }
       public Builder ClearName() {
+        PrepareBuilder();
         result.hasName = false;
         result.name_ = "";
         return this;
@@ -1465,11 +1597,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetId(value); }
       }
       public Builder SetId(int value) {
+        PrepareBuilder();
         result.hasId = true;
         result.id_ = value;
         return this;
       }
       public Builder ClearId() {
+        PrepareBuilder();
         result.hasId = false;
         result.id_ = 0;
         return this;
@@ -1484,18 +1618,20 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetEmail(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasEmail = true;
         result.email_ = value;
         return this;
       }
       public Builder ClearEmail() {
+        PrepareBuilder();
         result.hasEmail = false;
         result.email_ = "";
         return this;
       }
       
       public pbc::IPopsicleList<int> CodesList {
-        get { return result.codes_; }
+        get { return PrepareBuilder().codes_; }
       }
       public int CodesCount {
         get { return result.CodesCount; }
@@ -1504,24 +1640,28 @@ namespace Google.ProtocolBuffers.TestProtos {
         return result.GetCodes(index);
       }
       public Builder SetCodes(int index, int value) {
+        PrepareBuilder();
         result.codes_[index] = value;
         return this;
       }
       public Builder AddCodes(int value) {
+        PrepareBuilder();
         result.codes_.Add(value);
         return this;
       }
       public Builder AddRangeCodes(scg::IEnumerable<int> values) {
+        PrepareBuilder();
         result.codes_.Add(values);
         return this;
       }
       public Builder ClearCodes() {
+        PrepareBuilder();
         result.codes_.Clear();
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> PhoneList {
-        get { return result.phone_; }
+        get { return PrepareBuilder().phone_; }
       }
       public int PhoneCount {
         get { return result.PhoneCount; }
@@ -1531,35 +1671,41 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_[index] = value;
         return this;
       }
       public Builder SetPhone(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.phone_.Add(value);
         return this;
       }
       public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.phone_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangePhone(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> values) {
+        PrepareBuilder();
         result.phone_.Add(values);
         return this;
       }
       public Builder ClearPhone() {
+        PrepareBuilder();
         result.phone_.Clear();
         return this;
       }
       
       public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> AddressesList {
-        get { return result.addresses_; }
+        get { return PrepareBuilder().addresses_; }
       }
       public int AddressesCount {
         get { return result.AddressesCount; }
@@ -1569,29 +1715,35 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetAddresses(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.addresses_[index] = value;
         return this;
       }
       public Builder SetAddresses(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.addresses_[index] = builderForValue.Build();
         return this;
       }
       public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.addresses_.Add(value);
         return this;
       }
       public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.addresses_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeAddresses(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> values) {
+        PrepareBuilder();
         result.addresses_.Add(values);
         return this;
       }
       public Builder ClearAddresses() {
+        PrepareBuilder();
         result.addresses_.Clear();
         return this;
       }
@@ -1715,7 +1867,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestInteropEmployeeIdLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.SerializableAttribute()]
@@ -1726,21 +1878,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestInteropEmployeeIdLite();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestInteropEmployeeIdLite cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
       
-      TestInteropEmployeeIdLite result = new TestInteropEmployeeIdLite();
+      bool builderIsReadOnly;
+      TestInteropEmployeeIdLite result;
+      
+      private TestInteropEmployeeIdLite PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestInteropEmployeeIdLite original = result;
+          result = new TestInteropEmployeeIdLite();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestInteropEmployeeIdLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestInteropEmployeeIdLite();
+        result = DefaultInstance ?? new TestInteropEmployeeIdLite();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestInteropEmployeeIdLite DefaultInstanceForType {
@@ -1748,12 +1927,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestInteropEmployeeIdLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestInteropEmployeeIdLite returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -1767,6 +1945,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestInteropEmployeeIdLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasNumber) {
           Number = other.Number;
         }
@@ -1778,6 +1957,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -1821,11 +2001,13 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetNumber(string value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasNumber = true;
         result.number_ = value;
         return this;
       }
       public Builder ClearNumber() {
+        PrepareBuilder();
         result.hasNumber = false;
         result.number_ = "";
         return this;

+ 41 - 11
src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportLiteProtoFile.cs

@@ -151,7 +151,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(ImportMessageLite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -161,21 +161,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new ImportMessageLite();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(ImportMessageLite cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      ImportMessageLite result;
       
-      ImportMessageLite result = new ImportMessageLite();
+      private ImportMessageLite PrepareBuilder() {
+        if (builderIsReadOnly) {
+          ImportMessageLite original = result;
+          result = new ImportMessageLite();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessageLite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessageLite();
+        result = DefaultInstance ?? new ImportMessageLite();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override ImportMessageLite DefaultInstanceForType {
@@ -183,12 +210,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessageLite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        ImportMessageLite returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -202,6 +228,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessageLite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessageLite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -213,6 +240,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -255,11 +283,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 41 - 11
src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportProtoFile.cs

@@ -170,7 +170,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(ImportMessage prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -180,21 +180,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new ImportMessage();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(ImportMessage cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      ImportMessage result;
       
-      ImportMessage result = new ImportMessage();
+      private ImportMessage PrepareBuilder() {
+        if (builderIsReadOnly) {
+          ImportMessage original = result;
+          result = new ImportMessage();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override ImportMessage MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new ImportMessage();
+        result = DefaultInstance ?? new ImportMessage();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override pbd::MessageDescriptor DescriptorForType {
@@ -206,12 +233,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override ImportMessage BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        ImportMessage returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessage other) {
@@ -225,6 +251,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(ImportMessage other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.ImportMessage.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasD) {
           D = other.D;
         }
@@ -237,6 +264,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         pb::UnknownFieldSet.Builder unknownFields = null;
         uint tag;
         string field_name;
@@ -292,11 +320,13 @@ namespace Google.ProtocolBuffers.TestProtos {
         set { SetD(value); }
       }
       public Builder SetD(int value) {
+        PrepareBuilder();
         result.hasD = true;
         result.d_ = value;
         return this;
       }
       public Builder ClearD() {
+        PrepareBuilder();
         result.hasD = false;
         result.d_ = 0;
         return this;

+ 43 - 11
src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteImportNonLiteProtoFile.cs

@@ -140,7 +140,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     public override Builder ToBuilder() { return CreateBuilder(this); }
     public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(TestLiteImportsNonlite prototype) {
-      return (Builder) new Builder().MergeFrom(prototype);
+      return new Builder(prototype);
     }
     
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -150,21 +150,48 @@ namespace Google.ProtocolBuffers.TestProtos {
       protected override Builder ThisBuilder {
         get { return this; }
       }
-      public Builder() {}
+      public Builder() {
+        result = DefaultInstance ?? new TestLiteImportsNonlite();
+        builderIsReadOnly = result == DefaultInstance;
+      }
+      internal Builder(TestLiteImportsNonlite cloneFrom) {
+        result = cloneFrom;
+        builderIsReadOnly = true;
+      }
+      
+      bool builderIsReadOnly;
+      TestLiteImportsNonlite result;
       
-      TestLiteImportsNonlite result = new TestLiteImportsNonlite();
+      private TestLiteImportsNonlite PrepareBuilder() {
+        if (builderIsReadOnly) {
+          TestLiteImportsNonlite original = result;
+          result = new TestLiteImportsNonlite();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      public override bool IsInitialized {
+        get { return result.IsInitialized; }
+      }
       
       protected override TestLiteImportsNonlite MessageBeingBuilt {
-        get { return result; }
+        get { return PrepareBuilder(); }
       }
       
       public override Builder Clear() {
-        result = new TestLiteImportsNonlite();
+        result = DefaultInstance ?? new TestLiteImportsNonlite();
+        builderIsReadOnly = true;
         return this;
       }
       
       public override Builder Clone() {
-        return new Builder().MergeFrom(result);
+        if (builderIsReadOnly) {
+          return new Builder(result);
+        } else {
+          return new Builder().MergeFrom(result);
+        }
       }
       
       public override TestLiteImportsNonlite DefaultInstanceForType {
@@ -172,12 +199,11 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override TestLiteImportsNonlite BuildPartial() {
-        if (result == null) {
-          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        if (builderIsReadOnly) {
+          return result;
         }
-        TestLiteImportsNonlite returnMe = result;
-        result = null;
-        return returnMe;
+        builderIsReadOnly = true;
+        return result;
       }
       
       public override Builder MergeFrom(pb::IMessageLite other) {
@@ -191,6 +217,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       public override Builder MergeFrom(TestLiteImportsNonlite other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.TestLiteImportsNonlite.DefaultInstance) return this;
+        PrepareBuilder();
         if (other.HasMessage) {
           MergeMessage(other.Message);
         }
@@ -202,6 +229,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        PrepareBuilder();
         uint tag;
         string field_name;
         while (input.ReadTag(out tag, out field_name)) {
@@ -250,18 +278,21 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       public Builder SetMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         result.hasMessage = true;
         result.message_ = value;
         return this;
       }
       public Builder SetMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder builderForValue) {
         pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        PrepareBuilder();
         result.hasMessage = true;
         result.message_ = builderForValue.Build();
         return this;
       }
       public Builder MergeMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) {
         pb::ThrowHelper.ThrowIfNull(value, "value");
+        PrepareBuilder();
         if (result.hasMessage &&
             result.message_ != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance) {
             result.message_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(result.message_).MergeFrom(value).BuildPartial();
@@ -272,6 +303,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMessage() {
+        PrepareBuilder();
         result.hasMessage = false;
         result.message_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance;
         return this;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 249 - 51
src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteProtoFile.cs


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 249 - 51
src/ProtocolBuffersLite.Test/TestProtos/UnitTestProtoFile.cs


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä