فهرست منبع

First pass at implementation and testing of reusable builders.

csharptest 14 سال پیش
والد
کامیت
1a0764ab27
36فایلهای تغییر یافته به همراه4303 افزوده شده و 997 حذف شده
  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. 117 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. 164 44
      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. 188 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

@@ -223,7 +223,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()]
@@ -233,21 +233,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 {
@@ -259,12 +286,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) {
@@ -278,6 +304,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;
             }
@@ -293,6 +320,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;
@@ -361,11 +389,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;
@@ -379,11 +409,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;
@@ -527,7 +559,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()]
@@ -537,21 +569,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 {
@@ -563,13 +622,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) {
@@ -583,6 +641,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;
         }
@@ -604,6 +663,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;
@@ -672,11 +732,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;
@@ -690,11 +752,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;
@@ -709,18 +773,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; }
@@ -730,29 +796,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();
         base.AddRange(values, result.phone_);
         return this;
       }
       public Builder ClearPhone() {
+        PrepareBuilder();
         result.phone_.Clear();
         return this;
       }
@@ -869,7 +941,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()]
@@ -879,21 +951,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 {
@@ -905,13 +1004,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) {
@@ -925,6 +1023,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) {
           base.AddRange(other.person_, result.person_);
         }
@@ -937,6 +1036,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;
@@ -985,7 +1085,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; }
@@ -995,29 +1095,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();
         base.AddRange(values, result.person_);
         return this;
       }
       public Builder ClearPerson() {
+        PrepareBuilder();
         result.person_.Clear();
         return this;
       }

+ 2 - 0
src/ProtoGen/EnumFieldGenerator.cs

@@ -70,11 +70,13 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             AddClsComplianceCheck(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("}");
             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

@@ -68,18 +68,21 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             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("}");
             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;");
             writer.WriteLine("}");
             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,
@@ -91,6 +94,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             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

@@ -551,7 +551,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();
             writer.WriteLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]");
@@ -582,21 +582,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)
@@ -613,17 +644,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();
@@ -644,6 +673,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);
@@ -676,6 +706,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

@@ -72,11 +72,13 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddClsComplianceCheck(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("}");
             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

@@ -71,7 +71,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             // Note:  We can return the original list here, because we make it unmodifiable when we build
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
             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("}");
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return result.{0}Count; }}", PropertyName);
@@ -80,18 +80,22 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("  return result.Get{0}(index);", PropertyName);
             writer.WriteLine("}");
             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("}");
             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("}");
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  base.AddRange(values, result.{0}_);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             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

@@ -67,7 +67,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             // Note:  We can return the original list here, because we make it unmodifiable when we build
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
             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("}");
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return result.{0}Count; }}", PropertyName);
@@ -77,31 +77,37 @@ namespace Google.ProtocolBuffers.ProtoGen
             writer.WriteLine("}");
             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("}");
             // Extra overload for builder (just on messages)
             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("}");
             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("}");
             // Extra overload for builder (just on messages)
             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("}");
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  base.AddRange(values, result.{0}_);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             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

@@ -74,7 +74,7 @@ namespace Google.ProtocolBuffers.ProtoGen
             // We return it via IPopsicleList so that collection initializers work more pleasantly.
             AddClsComplianceCheck(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("}");
             writer.WriteLine("public int {0}Count {{", PropertyName);
             writer.WriteLine("  get {{ return result.{0}Count; }}", PropertyName);
@@ -86,21 +86,25 @@ namespace Google.ProtocolBuffers.ProtoGen
             AddClsComplianceCheck(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("}");
             AddClsComplianceCheck(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("}");
             AddClsComplianceCheck(writer);
             writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
+            writer.WriteLine("  PrepareBuilder();");
             writer.WriteLine("  base.AddRange(values, result.{0}_);", Name);
             writer.WriteLine("  return this;");
             writer.WriteLine("}");
             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

@@ -105,6 +105,7 @@
     <Compile Include="NameHelpersTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ReflectionTester.cs" />
+    <Compile Include="ReusableBuilderTest.cs" />
     <Compile Include="ServiceTest.cs" />
     <Compile Include="TestProtos\UnitTestCSharpOptionsProtoFile.cs" />
     <Compile Include="TestProtos\UnitTestCustomOptionsProtoFile.cs" />

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

@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using Google.ProtocolBuffers.TestProtos;
+
+namespace Google.ProtocolBuffers
+{
+    [TestFixture]
+    public class ReusableBuilderTest
+    {
+        [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 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 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 CloneOnAddRepeatedForeignMessage()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.AddRepeatedForeignMessage(ForeignMessage.DefaultInstance);
+            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 CloneOnAddRepeatedForeignEnum()
+        {
+            TestAllTypes.Builder builder = TestAllTypes.DefaultInstance.ToBuilder();
+            Assert.IsTrue(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+            builder.AddRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
+            Assert.IsFalse(ReferenceEquals(TestAllTypes.DefaultInstance, builder.Build()));
+        }
+
+    }
+}

+ 45 - 11
src/ProtocolBuffers.Test/TestProtos/UnitTestCSharpOptionsProtoFile.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(OptionsMessage 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 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 {
@@ -226,12 +253,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) {
@@ -245,6 +271,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;
         }
@@ -263,6 +290,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;
@@ -327,11 +355,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;
@@ -346,11 +376,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;
@@ -365,11 +397,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;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 425 - 116
src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs


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

@@ -186,7 +186,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()]
@@ -196,21 +196,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 {
@@ -222,13 +249,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) {
@@ -242,6 +268,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);
         }
@@ -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;
@@ -322,18 +350,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();
@@ -344,13 +375,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; }
@@ -360,29 +392,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();
         base.AddRange(values, result.repeatedMessage_);
         return this;
       }
       public Builder ClearRepeatedMessage() {
+        PrepareBuilder();
         result.repeatedMessage_.Clear();
         return this;
       }

+ 164 - 44
src/ProtocolBuffers.Test/TestProtos/UnitTestExtrasIssuesProtoFile.cs

@@ -175,7 +175,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()]
@@ -185,21 +185,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;
       
-      A result = new A();
+      private A PrepareBuilder() {
+        if (builderIsReadOnly) {
+          A original = result;
+          result = new A();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      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 {
@@ -211,12 +238,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) {
@@ -230,6 +256,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_;
         }
@@ -242,6 +269,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;
@@ -297,11 +325,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;
@@ -414,7 +444,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()]
@@ -424,21 +454,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;
       
-      B result = new B();
+      private B PrepareBuilder() {
+        if (builderIsReadOnly) {
+          B original = result;
+          result = new B();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      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 {
@@ -450,12 +507,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) {
@@ -469,6 +525,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_;
         }
@@ -481,6 +538,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;
@@ -536,11 +594,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;
@@ -653,7 +713,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()]
@@ -663,21 +723,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;
       
-      AB result = new AB();
+      private AB PrepareBuilder() {
+        if (builderIsReadOnly) {
+          AB original = result;
+          result = new AB();
+          builderIsReadOnly = false;
+          MergeFrom(original);
+        }
+        return result;
+      }
+      
+      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 {
@@ -689,12 +776,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) {
@@ -708,6 +794,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_;
         }
@@ -720,6 +807,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;
@@ -775,11 +863,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;
@@ -894,7 +984,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()]
@@ -904,21 +994,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 {
@@ -930,12 +1047,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) {
@@ -949,6 +1065,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;
         }
@@ -961,6 +1078,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;
@@ -1018,11 +1136,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;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 195 - 23
src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSizeProtoFile.cs


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 195 - 23
src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSpeedProtoFile.cs


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

@@ -150,7 +150,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()]
@@ -160,21 +160,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 {
@@ -182,12 +209,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) {
@@ -201,6 +227,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;
         }
@@ -212,6 +239,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)) {
@@ -254,11 +282,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

@@ -169,7 +169,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()]
@@ -179,21 +179,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 {
@@ -205,12 +232,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) {
@@ -224,6 +250,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;
         }
@@ -236,6 +263,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;
@@ -291,11 +319,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

@@ -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(TestMessageSet 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 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 {
@@ -225,12 +252,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) {
@@ -244,6 +270,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;
@@ -254,6 +281,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;
@@ -404,7 +432,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()]
@@ -414,21 +442,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 {
@@ -440,12 +495,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) {
@@ -459,6 +513,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);
         }
@@ -471,6 +526,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;
@@ -532,18 +588,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();
@@ -554,6 +613,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMessageSet() {
+        PrepareBuilder();
         result.hasMessageSet = false;
         result.messageSet_ = global::Google.ProtocolBuffers.TestProtos.TestMessageSet.DefaultInstance;
         return this;
@@ -668,7 +728,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()]
@@ -678,21 +738,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 {
@@ -704,12 +791,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) {
@@ -723,6 +809,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;
         }
@@ -735,6 +822,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;
@@ -790,11 +878,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;
@@ -909,7 +999,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()]
@@ -919,21 +1009,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 {
@@ -945,12 +1062,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) {
@@ -964,6 +1080,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;
         }
@@ -976,6 +1093,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;
@@ -1032,11 +1150,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;
@@ -1199,7 +1319,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()]
@@ -1209,21 +1329,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 {
@@ -1235,12 +1382,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) {
@@ -1254,6 +1400,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;
             }
@@ -1269,6 +1416,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;
@@ -1328,11 +1476,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;
@@ -1347,11 +1497,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;
@@ -1442,7 +1594,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()]
@@ -1452,21 +1604,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 {
@@ -1478,13 +1657,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) {
@@ -1498,6 +1676,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) {
           base.AddRange(other.item_, result.item_);
         }
@@ -1510,6 +1689,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;
@@ -1558,7 +1738,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; }
@@ -1568,29 +1748,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();
         base.AddRange(values, result.item_);
         return this;
       }
       public Builder ClearItem() {
+        PrepareBuilder();
         result.item_.Clear();
         return this;
       }

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

@@ -183,7 +183,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()]
@@ -193,21 +193,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 {
@@ -219,12 +246,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) {
@@ -238,6 +264,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;
         }
@@ -251,6 +278,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;
@@ -306,11 +334,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

@@ -164,7 +164,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()]
@@ -174,21 +174,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 {
@@ -200,12 +227,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;
       }
       
       
@@ -217,11 +243,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;
@@ -236,18 +264,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();
@@ -258,6 +289,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMsg() {
+        PrepareBuilder();
         result.hasMsg = false;
         result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance;
         return this;
@@ -337,7 +369,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()]
@@ -347,21 +379,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 {
@@ -373,12 +432,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;
       }
       
       
@@ -390,11 +448,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;
@@ -474,7 +534,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()]
@@ -484,21 +544,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 {
@@ -510,12 +597,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;
       }
       
       
@@ -528,18 +614,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();
@@ -550,6 +639,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearO() {
+        PrepareBuilder();
         result.hasO = false;
         result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance;
         return this;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 249 - 51
src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs


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

@@ -188,7 +188,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()]
@@ -198,21 +198,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 {
@@ -224,13 +251,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) {
@@ -244,6 +270,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) {
           base.AddRange(other.criteria_, result.criteria_);
         }
@@ -256,6 +283,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;
@@ -304,7 +332,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; }
@@ -314,19 +342,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();
         base.AddRange(values, result.criteria_);
         return this;
       }
       public Builder ClearCriteria() {
+        PrepareBuilder();
         result.criteria_.Clear();
         return this;
       }
@@ -487,7 +519,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()]
@@ -497,21 +529,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 {
@@ -523,12 +582,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) {
@@ -542,6 +600,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;
             }
@@ -557,6 +616,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;
@@ -617,11 +677,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;
@@ -636,11 +698,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;
@@ -734,7 +798,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()]
@@ -744,21 +808,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 {
@@ -770,13 +861,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) {
@@ -790,6 +880,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) {
           base.AddRange(other.results_, result.results_);
         }
@@ -802,6 +893,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;
@@ -850,7 +942,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; }
@@ -860,29 +952,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();
         base.AddRange(values, result.results_);
         return this;
       }
       public Builder ClearResults() {
+        PrepareBuilder();
         result.results_.Clear();
         return this;
       }
@@ -1019,7 +1117,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()]
@@ -1029,21 +1127,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 {
@@ -1055,13 +1180,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) {
@@ -1075,6 +1199,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) {
           base.AddRange(other.criteria_, result.criteria_);
         }
@@ -1090,6 +1215,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;
@@ -1147,7 +1273,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; }
@@ -1157,19 +1283,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();
         base.AddRange(values, result.criteria_);
         return this;
       }
       public Builder ClearCriteria() {
+        PrepareBuilder();
         result.criteria_.Clear();
         return this;
       }
@@ -1183,18 +1313,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();
@@ -1205,6 +1338,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

@@ -261,7 +261,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -271,21 +271,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 {
@@ -297,13 +324,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) {
@@ -317,6 +343,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) {
           base.AddRange(other.options_, result.options_);
         }
@@ -332,6 +359,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;
@@ -394,7 +422,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; }
@@ -403,18 +431,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();
         base.AddRange(values, result.options_);
         return this;
       }
       public Builder ClearOptions() {
+        PrepareBuilder();
         result.options_.Clear();
         return this;
       }
@@ -428,11 +460,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;
@@ -529,7 +563,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -539,21 +573,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 {
@@ -565,12 +626,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) {
@@ -584,6 +644,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;
       }
@@ -593,6 +654,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;
@@ -743,7 +805,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -753,21 +815,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 {
@@ -779,12 +868,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) {
@@ -798,6 +886,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);
         }
@@ -810,6 +899,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;
@@ -871,18 +961,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();
@@ -893,6 +986,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearChild() {
+        PrepareBuilder();
         result.hasChild = false;
         result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance;
         return this;
@@ -1062,7 +1156,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1072,21 +1166,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 {
@@ -1098,13 +1219,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) {
@@ -1118,6 +1238,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) {
               base.AddRange(other.options_, result.options_);
             }
@@ -1133,6 +1254,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;
@@ -1195,7 +1317,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; }
@@ -1204,18 +1326,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();
             base.AddRange(values, result.options_);
             return this;
           }
           public Builder ClearOptions() {
+            PrepareBuilder();
             result.options_.Clear();
             return this;
           }
@@ -1229,11 +1355,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;
@@ -1438,7 +1566,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1448,21 +1576,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 {
@@ -1474,15 +1629,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) {
@@ -1496,6 +1650,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;
         }
@@ -1527,6 +1682,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;
@@ -1612,18 +1768,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; }
@@ -1632,18 +1790,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();
         base.AddRange(values, result.numbers_);
         return this;
       }
       public Builder ClearNumbers() {
+        PrepareBuilder();
         result.numbers_.Clear();
         return this;
       }
@@ -1657,18 +1819,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; }
@@ -1678,19 +1842,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();
         base.AddRange(values, result.textlines_);
         return this;
       }
       public Builder ClearTextlines() {
+        PrepareBuilder();
         result.textlines_.Clear();
         return this;
       }
@@ -1703,11 +1871,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;
@@ -1722,18 +1892,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();
@@ -1744,13 +1917,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; }
@@ -1760,29 +1934,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();
         base.AddRange(values, result.children_);
         return this;
       }
       public Builder ClearChildren() {
+        PrepareBuilder();
         result.children_.Clear();
         return this;
       }
@@ -1895,7 +2075,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1905,21 +2085,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 {
@@ -1931,12 +2138,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) {
@@ -1950,6 +2156,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;
         }
@@ -1962,6 +2169,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;
@@ -2017,11 +2225,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;

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

@@ -415,7 +415,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()]
@@ -425,21 +425,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 {
@@ -451,12 +478,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) {
@@ -470,6 +496,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;
         }
@@ -518,6 +545,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;
@@ -630,11 +658,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;
@@ -649,11 +679,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;
@@ -667,11 +699,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;
@@ -685,11 +719,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;
@@ -703,11 +739,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;
@@ -721,11 +759,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;
@@ -739,11 +779,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;
@@ -757,11 +799,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;
@@ -776,11 +820,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;
@@ -795,11 +841,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;
@@ -814,11 +862,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;
@@ -832,11 +882,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;
@@ -850,11 +902,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;
@@ -967,7 +1021,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()]
@@ -977,21 +1031,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 {
@@ -1003,12 +1084,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) {
@@ -1022,6 +1102,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;
         }
@@ -1034,6 +1115,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;
@@ -1090,11 +1172,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;
@@ -1207,7 +1291,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()]
@@ -1217,21 +1301,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 {
@@ -1243,12 +1354,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) {
@@ -1262,6 +1372,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;
         }
@@ -1274,6 +1385,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;
@@ -1330,11 +1442,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;
@@ -1447,7 +1561,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()]
@@ -1457,21 +1571,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 {
@@ -1483,12 +1624,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) {
@@ -1502,6 +1642,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;
         }
@@ -1514,6 +1655,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;
@@ -1569,11 +1711,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;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 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
@@ -123,7 +118,7 @@ namespace Google.ProtocolBuffers
 
         public override MessageDescriptor DescriptorForType
         {
-            get { return MessageBeingBuilt.DescriptorForType; }
+            get { return DefaultInstanceForType.DescriptorForType; }
         }
 
         public override int GetRepeatedFieldCount(FieldDescriptor field)
@@ -230,7 +225,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>
         /// Adds all of the specified values to the given collection.
         /// </summary>
@@ -122,7 +117,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);
             }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 355 - 88
src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasFullProtoFile.cs


+ 240 - 58
src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasLiteProtoFile.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(TestRequiredLite 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 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 {
@@ -219,12 +246,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) {
@@ -238,6 +264,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;
         }
@@ -252,6 +279,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)) {
@@ -302,11 +330,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;
@@ -320,11 +350,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;
@@ -498,7 +530,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -508,21 +540,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 {
@@ -530,12 +589,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) {
@@ -549,6 +607,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;
             }
@@ -563,6 +622,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)) {
@@ -614,11 +674,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;
@@ -632,11 +694,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;
@@ -839,7 +903,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -849,21 +913,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 {
@@ -871,12 +962,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) {
@@ -890,6 +980,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;
             }
@@ -913,6 +1004,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)) {
@@ -972,11 +1064,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;
@@ -991,11 +1085,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;
@@ -1010,11 +1106,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;
@@ -1029,11 +1127,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;
@@ -1049,11 +1149,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;
@@ -1290,7 +1392,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1300,21 +1402,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 {
@@ -1322,15 +1451,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) {
@@ -1344,6 +1472,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;
         }
@@ -1371,6 +1500,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)) {
@@ -1435,11 +1565,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;
@@ -1453,11 +1585,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;
@@ -1472,18 +1606,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; }
@@ -1492,24 +1628,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();
         base.AddRange(values, result.codes_);
         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; }
@@ -1519,35 +1659,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();
         base.AddRange(values, result.phone_);
         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; }
@@ -1557,29 +1703,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();
         base.AddRange(values, result.addresses_);
         return this;
       }
       public Builder ClearAddresses() {
+        PrepareBuilder();
         result.addresses_.Clear();
         return this;
       }
@@ -1701,7 +1853,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.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -1711,21 +1863,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 {
@@ -1733,12 +1912,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) {
@@ -1752,6 +1930,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;
         }
@@ -1763,6 +1942,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)) {
@@ -1806,11 +1986,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

@@ -150,7 +150,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()]
@@ -160,21 +160,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 {
@@ -182,12 +209,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) {
@@ -201,6 +227,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;
         }
@@ -212,6 +239,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)) {
@@ -254,11 +282,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

@@ -169,7 +169,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()]
@@ -179,21 +179,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 {
@@ -205,12 +232,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) {
@@ -224,6 +250,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;
         }
@@ -236,6 +263,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;
@@ -291,11 +319,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

@@ -139,7 +139,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()]
@@ -149,21 +149,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 {
@@ -171,12 +198,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) {
@@ -190,6 +216,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);
         }
@@ -201,6 +228,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)) {
@@ -249,18 +277,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();
@@ -271,6 +302,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder ClearMessage() {
+        PrepareBuilder();
         result.hasMessage = false;
         result.message_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance;
         return this;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 249 - 51
src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteProtoFile.cs


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 249 - 51
src/ProtocolBuffersLite.Test/TestProtos/UnitTestProtoFile.cs


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است