Browse Source

The great generics revisiting.

Jon Skeet 17 năm trước cách đây
mục cha
commit
f26f8dce02
36 tập tin đã thay đổi với 960 bổ sung1008 xóa
  1. 35 28
      csharp/ProtocolBuffers.Test/AbstractMessageTest.cs
  2. 5 5
      csharp/ProtocolBuffers.Test/DynamicMessageTest.cs
  3. 2 4
      csharp/ProtocolBuffers.Test/MessageTest.cs
  4. 66 66
      csharp/ProtocolBuffers.Test/ReflectionTester.cs
  5. 14 6
      csharp/ProtocolBuffers.Test/TestProtos/MessageWithNoOuter.cs
  6. 2 2
      csharp/ProtocolBuffers.Test/TestProtos/MultiFileProto.cs
  7. 1 1
      csharp/ProtocolBuffers.Test/TestProtos/ServiceWithNoOuter.cs
  8. 11 11
      csharp/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
  9. 11 11
      csharp/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
  10. 70 70
      csharp/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
  11. 9 5
      csharp/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs
  12. 252 252
      csharp/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
  13. 91 71
      csharp/ProtocolBuffers/AbstractBuilder.cs
  14. 13 15
      csharp/ProtocolBuffers/AbstractMessage.cs
  15. 2 2
      csharp/ProtocolBuffers/CodedInputStream.cs
  16. 162 162
      csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  17. 43 35
      csharp/ProtocolBuffers/DynamicMessage.cs
  18. 14 17
      csharp/ProtocolBuffers/ExtendableBuilder.cs
  19. 7 7
      csharp/ProtocolBuffers/ExtendableMessage.cs
  20. 1 2
      csharp/ProtocolBuffers/ExtensionRegistry.cs
  21. 1 1
      csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
  22. 1 1
      csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
  23. 14 14
      csharp/ProtocolBuffers/FieldSet.cs
  24. 17 95
      csharp/ProtocolBuffers/GeneratedBuilder.cs
  25. 3 3
      csharp/ProtocolBuffers/GeneratedExtensionBase.cs
  26. 2 14
      csharp/ProtocolBuffers/GeneratedMessage.cs
  27. 3 3
      csharp/ProtocolBuffers/GeneratedRepeatException.cs
  28. 3 5
      csharp/ProtocolBuffers/GeneratedSingleExtension.cs
  29. 59 56
      csharp/ProtocolBuffers/IBuilder.cs
  30. 17 23
      csharp/ProtocolBuffers/IMessage.cs
  31. 2 2
      csharp/ProtocolBuffers/InvalidProtocolBufferException.cs
  32. 5 4
      csharp/ProtocolBuffers/RpcUtil.cs
  33. 1 0
      csharp/ProtocolBuffers/TextFormat.cs
  34. 4 4
      src/google/protobuf/compiler/csharp/csharp_extension.cc
  35. 16 10
      src/google/protobuf/compiler/csharp/csharp_message.cc
  36. 1 1
      src/google/protobuf/compiler/csharp/csharp_service.cc

+ 35 - 28
csharp/ProtocolBuffers.Test/AbstractMessageTest.cs

@@ -10,15 +10,13 @@ namespace Google.ProtocolBuffers {
 
     [Test]
     public void Clear() {
-      AbstractMessageWrapper message = (AbstractMessageWrapper)
-        new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(TestUtil.GetAllSet())).Clear().Build();
+      AbstractMessageWrapper message = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(TestUtil.GetAllSet())).Clear().Build();
       TestUtil.AssertClear((TestAllTypes) message.WrappedMessage);
     }
 
     [Test]
     public void Copy() {
-      AbstractMessageWrapper message = (AbstractMessageWrapper)
-        new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()).MergeFrom(TestUtil.GetAllSet()).Build();
+      AbstractMessageWrapper message = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()).MergeFrom(TestUtil.GetAllSet()).Build();
       TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage);
     }
 
@@ -40,7 +38,7 @@ namespace Google.ProtocolBuffers {
     [Test]
     public void Parsing() {
       IBuilder builder = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder());
-      AbstractMessageWrapper message = (AbstractMessageWrapper) builder.MergeFrom(TestUtil.GetAllSet().ToByteString()).Build();
+      AbstractMessageWrapper message = (AbstractMessageWrapper) builder.WeakMergeFrom(TestUtil.GetAllSet().ToByteString()).WeakBuild();
       TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage);
     }
 
@@ -177,7 +175,7 @@ namespace Google.ProtocolBuffers {
       Assert.AreEqual(message, message);
       
       // Object should be equal to a dynamic copy of itself.
-      DynamicMessage dynamic = (DynamicMessage) ((IBuilder) DynamicMessage.CreateBuilder(message)).Build();
+      DynamicMessage dynamic = DynamicMessage.CreateBuilder(message).Build();
       Assert.AreEqual(message, dynamic);
       Assert.AreEqual(dynamic, message);
       Assert.AreEqual(dynamic.GetHashCode(), message.GetHashCode());
@@ -207,7 +205,7 @@ namespace Google.ProtocolBuffers {
     /// test that AbstractMessage's implementations work even if the wrapped
     /// object does not use them.
     /// </summary>
-    private class AbstractMessageWrapper : AbstractMessage {
+    private class AbstractMessageWrapper : AbstractMessage<AbstractMessageWrapper, AbstractMessageWrapper.Builder> {
       private readonly IMessage wrappedMessage;
 
       public IMessage WrappedMessage {
@@ -222,8 +220,8 @@ namespace Google.ProtocolBuffers {
         get { return wrappedMessage.DescriptorForType; }
       }
 
-      protected override IMessage DefaultInstanceForTypeImpl {
-        get { return new AbstractMessageWrapper(wrappedMessage.DefaultInstanceForType); }
+      public override AbstractMessageWrapper DefaultInstanceForType {
+        get { return new AbstractMessageWrapper(wrappedMessage.WeakDefaultInstanceForType); }
       }
 
       public override IDictionary<FieldDescriptor, object> AllFields {
@@ -250,17 +248,26 @@ namespace Google.ProtocolBuffers {
         get { return wrappedMessage.UnknownFields; }
       }
 
-      protected override IBuilder CreateBuilderForTypeImpl() {
-        return new Builder(wrappedMessage.CreateBuilderForType());
+      public override Builder CreateBuilderForType() {
+        return new Builder(wrappedMessage.WeakCreateBuilderForType());
       }
 
-      internal class Builder : AbstractBuilder {
+      internal class Builder : AbstractBuilder<AbstractMessageWrapper, Builder> {
         private readonly IBuilder wrappedBuilder;
 
+        protected override Builder ThisBuilder {
+          get { return this; }
+        }
+
         internal Builder(IBuilder wrappedBuilder) {
           this.wrappedBuilder = wrappedBuilder;
         }
 
+        public override Builder MergeFrom(AbstractMessageWrapper other) {
+          wrappedBuilder.WeakMergeFrom(other.wrappedMessage);
+          return this;
+        }
+
         public override bool IsInitialized {
           get { return wrappedBuilder.IsInitialized; }
         }
@@ -296,29 +303,29 @@ namespace Google.ProtocolBuffers {
           set { wrappedBuilder.UnknownFields = value; }
         }
 
-        protected override IMessage BuildImpl() {
-          return new AbstractMessageWrapper(wrappedBuilder.Build());
+        public override AbstractMessageWrapper Build() {
+          return new AbstractMessageWrapper(wrappedBuilder.WeakBuild());
         }
 
-        protected override IMessage BuildPartialImpl() {
-          return new AbstractMessageWrapper(wrappedBuilder.BuildPartial());
+        public override AbstractMessageWrapper BuildPartial() {
+          return new AbstractMessageWrapper(wrappedBuilder.WeakBuildPartial());
         }
 
-        protected override IBuilder CloneImpl() {
-          return new Builder(wrappedBuilder.Clone());
+        public override Builder Clone() {
+          return new Builder(wrappedBuilder.WeakClone());
         }
 
-        protected override IMessage DefaultInstanceForTypeImpl {
-          get { return wrappedBuilder.DefaultInstanceForType; }
+        public override AbstractMessageWrapper DefaultInstanceForType {
+          get { return new AbstractMessageWrapper(wrappedBuilder.WeakDefaultInstanceForType); }
         }
 
-        protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
-          wrappedBuilder.ClearField(field);
+        public override Builder ClearField(FieldDescriptor field) {
+          wrappedBuilder.WeakClearField(field);
           return this;
         }
 
-        protected override IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value) {
-          wrappedBuilder.AddRepeatedField(field, value);
+        public override Builder AddRepeatedField(FieldDescriptor field, object value) {
+          wrappedBuilder.WeakAddRepeatedField(field, value);
           return this;
         }
 
@@ -327,13 +334,13 @@ namespace Google.ProtocolBuffers {
           return this;
         }
 
-        public override IBuilder MergeFrom(IMessage other) {
-          wrappedBuilder.MergeFrom(other);
+        public override Builder MergeFrom(IMessage other) {
+          wrappedBuilder.WeakMergeFrom(other);
           return this;
         }
 
-        protected override IBuilder MergeFromImpl(CodedInputStream input, ExtensionRegistry extensionRegistry) {
-          wrappedBuilder.MergeFrom(input, extensionRegistry);
+        public override Builder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
+          wrappedBuilder.WeakMergeFrom(input, extensionRegistry);
           return this;
         }
       }

+ 5 - 5
csharp/ProtocolBuffers.Test/DynamicMessageTest.cs

@@ -21,7 +21,7 @@ namespace Google.ProtocolBuffers {
     public void DynamicMessageAccessors() {
       IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
       reflectionTester.SetAllFieldsViaReflection(builder);
-      IMessage message = builder.Build();
+      IMessage message = builder.WeakBuild();
       reflectionTester.AssertAllFieldsSetViaReflection(message);
     }
 
@@ -32,7 +32,7 @@ namespace Google.ProtocolBuffers {
     // It treats them just like any other fields.
     IBuilder builder = DynamicMessage.CreateBuilder(TestAllExtensions.Descriptor);
     extensionsReflectionTester.SetAllFieldsViaReflection(builder);
-    IMessage message = builder.Build();
+    IMessage message = builder.WeakBuild();
     extensionsReflectionTester.AssertAllFieldsSetViaReflection(message);
   }
 
@@ -41,7 +41,7 @@ namespace Google.ProtocolBuffers {
       IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
       reflectionTester.SetAllFieldsViaReflection(builder);
       reflectionTester.ModifyRepeatedFieldsViaReflection(builder);
-      IMessage message = builder.Build();
+      IMessage message = builder.WeakBuild();
       reflectionTester.AssertRepeatedFieldsModifiedViaReflection(message);
     }
 
@@ -57,7 +57,7 @@ namespace Google.ProtocolBuffers {
 
       IBuilder dynamicBuilder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
       reflectionTester.SetAllFieldsViaReflection(dynamicBuilder);
-      IMessage dynamicMessage = dynamicBuilder.Build();
+      IMessage dynamicMessage = dynamicBuilder.WeakBuild();
 
       Assert.AreEqual(message.SerializedSize, dynamicMessage.SerializedSize);
     }
@@ -66,7 +66,7 @@ namespace Google.ProtocolBuffers {
     public void DynamicMessageSerialization() {
       IBuilder builder =  DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
       reflectionTester.SetAllFieldsViaReflection(builder);
-      IMessage message = builder.Build();
+      IMessage message = builder.WeakBuild();
 
       ByteString rawBytes = message.ToByteString();
       TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);

+ 2 - 4
csharp/ProtocolBuffers.Test/MessageTest.cs

@@ -153,8 +153,7 @@ namespace Google.ProtocolBuffers {
       builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredInitialized;
       Assert.IsTrue(builder.IsInitialized);
 
-      // TODO(jonskeet): Remove this nastiness by making IBuilder always generic.
-      ((IBuilder) builder).AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), TestRequiredUninitialized);
+      builder.AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), TestRequiredUninitialized);
       Assert.IsFalse(builder.IsInitialized);
 
       builder.SetRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), 0, TestRequiredInitialized);
@@ -266,8 +265,7 @@ namespace Google.ProtocolBuffers {
     [Test]
     public void DynamicBuildPartial() {
       // We're mostly testing that no exception is thrown.
-      // TODO(jonskeet): Fix this ghastly casting mess
-      DynamicMessage message = (DynamicMessage) ((IBuilder) DynamicMessage.CreateBuilder(TestRequired.Descriptor)).BuildPartial();
+      DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial();
       Assert.IsFalse(message.Initialized);
     }
 

+ 66 - 66
csharp/ProtocolBuffers.Test/ReflectionTester.cs

@@ -170,7 +170,7 @@ namespace Google.ProtocolBuffers {
         ExtensionInfo extension = extensionRegistry[field.ContainingType, field.FieldNumber];
         Assert.IsNotNull(extension);
         Assert.IsNotNull(extension.DefaultInstance);
-        return extension.DefaultInstance.CreateBuilderForType();
+        return extension.DefaultInstance.WeakCreateBuilderForType();
       }
     }
 
@@ -196,10 +196,10 @@ namespace Google.ProtocolBuffers {
       message[f("optional_string"  )] = "115";
       message[f("optional_bytes")] = TestUtil.ToBytes("116");
 
-      message[f("optionalgroup")] = CreateBuilderForField(message, f("optionalgroup")).SetField(groupA, 117).Build();
-      message[f("optional_nested_message")] = CreateBuilderForField(message, f("optional_nested_message")).SetField(nestedB, 118).Build();
-      message[f("optional_foreign_message")] = CreateBuilderForField(message, f("optional_foreign_message")).SetField(foreignC, 119).Build();
-      message[f("optional_import_message")] = CreateBuilderForField(message, f("optional_import_message")).SetField(importD, 120).Build();
+      message[f("optionalgroup")] = CreateBuilderForField(message, f("optionalgroup")).SetField(groupA, 117).WeakBuild();
+      message[f("optional_nested_message")] = CreateBuilderForField(message, f("optional_nested_message")).SetField(nestedB, 118).WeakBuild();
+      message[f("optional_foreign_message")] = CreateBuilderForField(message, f("optional_foreign_message")).SetField(foreignC, 119).WeakBuild();
+      message[f("optional_import_message")] = CreateBuilderForField(message, f("optional_import_message")).SetField(importD, 120).WeakBuild();
 
       message[f("optional_nested_enum" )] =  nestedBaz;
       message[f("optional_foreign_enum")] = foreignBaz;
@@ -210,71 +210,71 @@ namespace Google.ProtocolBuffers {
 
       // -----------------------------------------------------------------
 
-      message.AddRepeatedField(f("repeated_int32"   ), 201 );
-      message.AddRepeatedField(f("repeated_int64"   ), 202L);
-      message.AddRepeatedField(f("repeated_uint32"  ), 203U );
-      message.AddRepeatedField(f("repeated_uint64"  ), 204UL);
-      message.AddRepeatedField(f("repeated_sint32"  ), 205 );
-      message.AddRepeatedField(f("repeated_sint64"  ), 206L);
-      message.AddRepeatedField(f("repeated_fixed32" ), 207U );
-      message.AddRepeatedField(f("repeated_fixed64" ), 208UL);
-      message.AddRepeatedField(f("repeated_sfixed32"), 209 );
-      message.AddRepeatedField(f("repeated_sfixed64"), 210L);
-      message.AddRepeatedField(f("repeated_float"   ), 211F);
-      message.AddRepeatedField(f("repeated_double"  ), 212D);
-      message.AddRepeatedField(f("repeated_bool"    ), true);
-      message.AddRepeatedField(f("repeated_string"  ), "215");
-      message.AddRepeatedField(f("repeated_bytes"   ), TestUtil.ToBytes("216"));
-
-
-      message.AddRepeatedField(f("repeatedgroup"), CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 217).Build());
-      message.AddRepeatedField(f("repeated_nested_message"), CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 218).Build());
-      message.AddRepeatedField(f("repeated_foreign_message"), CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 219).Build());
-      message.AddRepeatedField(f("repeated_import_message"), CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 220).Build());
-
-      message.AddRepeatedField(f("repeated_nested_enum" ),  nestedBar);
-      message.AddRepeatedField(f("repeated_foreign_enum"), foreignBar);
-      message.AddRepeatedField(f("repeated_import_enum" ),  importBar);
-
-      message.AddRepeatedField(f("repeated_string_piece" ), "224");
-      message.AddRepeatedField(f("repeated_cord" ), "225");
+      message.WeakAddRepeatedField(f("repeated_int32"   ), 201 );
+      message.WeakAddRepeatedField(f("repeated_int64"   ), 202L);
+      message.WeakAddRepeatedField(f("repeated_uint32"  ), 203U );
+      message.WeakAddRepeatedField(f("repeated_uint64"  ), 204UL);
+      message.WeakAddRepeatedField(f("repeated_sint32"  ), 205 );
+      message.WeakAddRepeatedField(f("repeated_sint64"  ), 206L);
+      message.WeakAddRepeatedField(f("repeated_fixed32" ), 207U );
+      message.WeakAddRepeatedField(f("repeated_fixed64" ), 208UL);
+      message.WeakAddRepeatedField(f("repeated_sfixed32"), 209 );
+      message.WeakAddRepeatedField(f("repeated_sfixed64"), 210L);
+      message.WeakAddRepeatedField(f("repeated_float"   ), 211F);
+      message.WeakAddRepeatedField(f("repeated_double"  ), 212D);
+      message.WeakAddRepeatedField(f("repeated_bool"    ), true);
+      message.WeakAddRepeatedField(f("repeated_string"  ), "215");
+      message.WeakAddRepeatedField(f("repeated_bytes"   ), TestUtil.ToBytes("216"));
+
+
+      message.WeakAddRepeatedField(f("repeatedgroup"), CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 217).WeakBuild());
+      message.WeakAddRepeatedField(f("repeated_nested_message"), CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 218).WeakBuild());
+      message.WeakAddRepeatedField(f("repeated_foreign_message"), CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 219).WeakBuild());
+      message.WeakAddRepeatedField(f("repeated_import_message"), CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 220).WeakBuild());
+
+      message.WeakAddRepeatedField(f("repeated_nested_enum" ),  nestedBar);
+      message.WeakAddRepeatedField(f("repeated_foreign_enum"), foreignBar);
+      message.WeakAddRepeatedField(f("repeated_import_enum" ),  importBar);
+
+      message.WeakAddRepeatedField(f("repeated_string_piece" ), "224");
+      message.WeakAddRepeatedField(f("repeated_cord" ), "225");
 
       // Add a second one of each field.
-      message.AddRepeatedField(f("repeated_int32"   ), 301 );
-      message.AddRepeatedField(f("repeated_int64"   ), 302L);
-      message.AddRepeatedField(f("repeated_uint32"  ), 303U );
-      message.AddRepeatedField(f("repeated_uint64"  ), 304UL);
-      message.AddRepeatedField(f("repeated_sint32"  ), 305 );
-      message.AddRepeatedField(f("repeated_sint64"  ), 306L);
-      message.AddRepeatedField(f("repeated_fixed32" ), 307U );
-      message.AddRepeatedField(f("repeated_fixed64" ), 308UL);
-      message.AddRepeatedField(f("repeated_sfixed32"), 309 );
-      message.AddRepeatedField(f("repeated_sfixed64"), 310L);
-      message.AddRepeatedField(f("repeated_float"   ), 311F);
-      message.AddRepeatedField(f("repeated_double"  ), 312D);
-      message.AddRepeatedField(f("repeated_bool"    ), false);
-      message.AddRepeatedField(f("repeated_string"  ), "315");
-      message.AddRepeatedField(f("repeated_bytes"   ), TestUtil.ToBytes("316"));
-
-      message.AddRepeatedField(f("repeatedgroup"),
+      message.WeakAddRepeatedField(f("repeated_int32"   ), 301 );
+      message.WeakAddRepeatedField(f("repeated_int64"   ), 302L);
+      message.WeakAddRepeatedField(f("repeated_uint32"  ), 303U );
+      message.WeakAddRepeatedField(f("repeated_uint64"  ), 304UL);
+      message.WeakAddRepeatedField(f("repeated_sint32"  ), 305 );
+      message.WeakAddRepeatedField(f("repeated_sint64"  ), 306L);
+      message.WeakAddRepeatedField(f("repeated_fixed32" ), 307U );
+      message.WeakAddRepeatedField(f("repeated_fixed64" ), 308UL);
+      message.WeakAddRepeatedField(f("repeated_sfixed32"), 309 );
+      message.WeakAddRepeatedField(f("repeated_sfixed64"), 310L);
+      message.WeakAddRepeatedField(f("repeated_float"   ), 311F);
+      message.WeakAddRepeatedField(f("repeated_double"  ), 312D);
+      message.WeakAddRepeatedField(f("repeated_bool"    ), false);
+      message.WeakAddRepeatedField(f("repeated_string"  ), "315");
+      message.WeakAddRepeatedField(f("repeated_bytes"   ), TestUtil.ToBytes("316"));
+
+      message.WeakAddRepeatedField(f("repeatedgroup"),
         CreateBuilderForField(message, f("repeatedgroup"))
-               .SetField(repeatedGroupA, 317).Build());
-      message.AddRepeatedField(f("repeated_nested_message"),
+               .SetField(repeatedGroupA, 317).WeakBuild());
+      message.WeakAddRepeatedField(f("repeated_nested_message"),
         CreateBuilderForField(message, f("repeated_nested_message"))
-               .SetField(nestedB, 318).Build());
-      message.AddRepeatedField(f("repeated_foreign_message"),
+               .SetField(nestedB, 318).WeakBuild());
+      message.WeakAddRepeatedField(f("repeated_foreign_message"),
         CreateBuilderForField(message, f("repeated_foreign_message"))
-               .SetField(foreignC, 319).Build());
-      message.AddRepeatedField(f("repeated_import_message"),
+               .SetField(foreignC, 319).WeakBuild());
+      message.WeakAddRepeatedField(f("repeated_import_message"),
         CreateBuilderForField(message, f("repeated_import_message"))
-               .SetField(importD, 320).Build());
+               .SetField(importD, 320).WeakBuild());
 
-      message.AddRepeatedField(f("repeated_nested_enum" ),  nestedBaz);
-      message.AddRepeatedField(f("repeated_foreign_enum"), foreignBaz);
-      message.AddRepeatedField(f("repeated_import_enum" ),  importBaz);
+      message.WeakAddRepeatedField(f("repeated_nested_enum" ),  nestedBaz);
+      message.WeakAddRepeatedField(f("repeated_foreign_enum"), foreignBaz);
+      message.WeakAddRepeatedField(f("repeated_import_enum" ),  importBaz);
 
-      message.AddRepeatedField(f("repeated_string_piece" ), "324");
-      message.AddRepeatedField(f("repeated_cord" ), "325");
+      message.WeakAddRepeatedField(f("repeated_string_piece" ), "324");
+      message.WeakAddRepeatedField(f("repeated_cord" ), "325");
 
       // -----------------------------------------------------------------
 
@@ -326,10 +326,10 @@ namespace Google.ProtocolBuffers {
       message[f("repeated_string"  ), 1] = "515";
       message.SetRepeatedField(f("repeated_bytes"   ), 1, TestUtil.ToBytes("516"));
 
-      message.SetRepeatedField(f("repeatedgroup"), 1, CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 517).Build());
-      message.SetRepeatedField(f("repeated_nested_message"), 1, CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 518).Build());
-      message.SetRepeatedField(f("repeated_foreign_message"), 1, CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 519).Build());
-      message.SetRepeatedField(f("repeated_import_message"), 1, CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 520).Build());
+      message.SetRepeatedField(f("repeatedgroup"), 1, CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 517).WeakBuild());
+      message.SetRepeatedField(f("repeated_nested_message"), 1, CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 518).WeakBuild());
+      message.SetRepeatedField(f("repeated_foreign_message"), 1, CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 519).WeakBuild());
+      message.SetRepeatedField(f("repeated_import_message"), 1, CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 520).WeakBuild());
 
       message[f("repeated_nested_enum" ), 1] =  nestedFoo;
       message[f("repeated_foreign_enum"), 1] = foreignFoo;

+ 14 - 6
csharp/ProtocolBuffers.Test/TestProtos/MessageWithNoOuter.cs

@@ -95,12 +95,16 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
         
         public static Builder CreateBuilder() { return new Builder(); }
-        public override IBuilder<self::MessageWithNoOuter.Types.NestedMessage> CreateBuilderForType() { return new Builder(); }
+        public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(self::MessageWithNoOuter.Types.NestedMessage prototype) {
           return (Builder) new Builder().MergeFrom(prototype);
         }
         
         public sealed partial class Builder : pb::GeneratedBuilder<self::MessageWithNoOuter.Types.NestedMessage, Builder> {
+          protected override Builder ThisBuilder {
+            get { return this; }
+          }
+          
           // Construct using self::MessageWithNoOuter.Types.NestedMessage.CreateBuilder()
           internal Builder() {}
           
@@ -110,12 +114,12 @@ namespace Google.ProtocolBuffers.TestProtos {
             get { return result; }
           }
           
-          public override IBuilder<self::MessageWithNoOuter.Types.NestedMessage> Clear() {
+          public override Builder Clear() {
             result = new self::MessageWithNoOuter.Types.NestedMessage();
             return this;
           }
           
-          public override IBuilder<self::MessageWithNoOuter.Types.NestedMessage> Clone() {
+          public override Builder Clone() {
             return new Builder().MergeFrom(result);
           }
           
@@ -231,12 +235,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::MessageWithNoOuter> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::MessageWithNoOuter prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::GeneratedBuilder<self::MessageWithNoOuter, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::MessageWithNoOuter.CreateBuilder()
       internal Builder() {}
       
@@ -246,12 +254,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::MessageWithNoOuter> Clear() {
+      public override Builder Clear() {
         result = new self::MessageWithNoOuter();
         return this;
       }
       
-      public override IBuilder<self::MessageWithNoOuter> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       

+ 2 - 2
csharp/ProtocolBuffers.Test/TestProtos/MultiFileProto.cs

@@ -59,8 +59,8 @@ namespace Google.ProtocolBuffers.TestProtos {
     #endregion
     
     #region Extensions
-    public static readonly pb::GeneratedExtensionBase<self::TestAllExtensions, int> ExtensionWithOuter =
-          pb::GeneratedSingleExtension<self::TestAllExtensions, int>.CreateInstance(Descriptor.Extensions[0]);
+    public static readonly pb::GeneratedExtensionBase<int> ExtensionWithOuter =
+          pb::GeneratedSingleExtension<int>.CreateInstance(Descriptor.Extensions[0]);
     #endregion
     
     #region Static variables

+ 1 - 1
csharp/ProtocolBuffers.Test/TestProtos/ServiceWithNoOuter.cs

@@ -95,7 +95,7 @@ namespace Google.ProtocolBuffers.TestProtos {
           controller,
           request,
           self::TestAllTypes.DefaultInstance,
-          pb::RpcUtil.GeneralizeCallback(done, self::TestAllTypes.DefaultInstance));
+          pb::RpcUtil.GeneralizeCallback<self::TestAllTypes, self::TestAllTypes.Builder>(done, self::TestAllTypes.DefaultInstance));
       }
     }
   }

+ 11 - 11
csharp/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs

@@ -174,12 +174,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::TestEmbedOptimizedForSize> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::TestEmbedOptimizedForSize prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::GeneratedBuilder<self::TestEmbedOptimizedForSize, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::TestEmbedOptimizedForSize.CreateBuilder()
       internal Builder() {}
       
@@ -189,12 +193,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::TestEmbedOptimizedForSize> Clear() {
+      public override Builder Clear() {
         result = new self::TestEmbedOptimizedForSize();
         return this;
       }
       
-      public override IBuilder<self::TestEmbedOptimizedForSize> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       
@@ -215,11 +219,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return returnMe;
       }
       
-      protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-        return MergeFrom(data, extensionRegistry);
-      }
-      
-      public override IBuilder MergeFrom(pb::IMessage other) {
+      public override Builder MergeFrom(pb::IMessage other) {
         if (other is self::TestEmbedOptimizedForSize) {
           return MergeFrom((self::TestEmbedOptimizedForSize) other);
         } else {
@@ -228,7 +228,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
       }
       
-      public override IBuilder<self::TestEmbedOptimizedForSize> MergeFrom(self::TestEmbedOptimizedForSize other) {
+      public override Builder MergeFrom(self::TestEmbedOptimizedForSize other) {
         if (other == self::TestEmbedOptimizedForSize.DefaultInstance) return this;
         if (other.HasOptionalMessage) {
           MergeOptionalMessage(other.OptionalMessage);
@@ -243,11 +243,11 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       
-      public override IBuilder<self::TestEmbedOptimizedForSize> MergeFrom(pb::CodedInputStream input) {
+      public override Builder MergeFrom(pb::CodedInputStream input) {
         return MergeFrom(input, pb::ExtensionRegistry.Empty);
       }
       
-      public override IBuilder<self::TestEmbedOptimizedForSize> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
         pb::UnknownFieldSet.Builder unknownFields =
           pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
         while (true) {

+ 11 - 11
csharp/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs

@@ -150,12 +150,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::ImportMessage> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::ImportMessage prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::GeneratedBuilder<self::ImportMessage, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::ImportMessage.CreateBuilder()
       internal Builder() {}
       
@@ -165,12 +169,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::ImportMessage> Clear() {
+      public override Builder Clear() {
         result = new self::ImportMessage();
         return this;
       }
       
-      public override IBuilder<self::ImportMessage> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       
@@ -188,11 +192,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return returnMe;
       }
       
-      protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-        return MergeFrom(data, extensionRegistry);
-      }
-      
-      public override IBuilder MergeFrom(pb::IMessage other) {
+      public override Builder MergeFrom(pb::IMessage other) {
         if (other is self::ImportMessage) {
           return MergeFrom((self::ImportMessage) other);
         } else {
@@ -201,7 +201,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
       }
       
-      public override IBuilder<self::ImportMessage> MergeFrom(self::ImportMessage other) {
+      public override Builder MergeFrom(self::ImportMessage other) {
         if (other == self::ImportMessage.DefaultInstance) return this;
         if (other.HasD) {
           D = other.D;
@@ -210,11 +210,11 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       
-      public override IBuilder<self::ImportMessage> MergeFrom(pb::CodedInputStream input) {
+      public override Builder MergeFrom(pb::CodedInputStream input) {
         return MergeFrom(input, pb::ExtensionRegistry.Empty);
       }
       
-      public override IBuilder<self::ImportMessage> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
         pb::UnknownFieldSet.Builder unknownFields =
           pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
         while (true) {

+ 70 - 70
csharp/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs

@@ -188,12 +188,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::TestMessageSet> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::TestMessageSet prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::ExtendableBuilder<self::TestMessageSet, self::TestMessageSet.Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::TestMessageSet.CreateBuilder()
       internal Builder() {}
       
@@ -203,12 +207,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::TestMessageSet> Clear() {
+      public override Builder Clear() {
         result = new self::TestMessageSet();
         return this;
       }
       
-      public override IBuilder<self::TestMessageSet> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       
@@ -226,11 +230,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return returnMe;
       }
       
-      protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-        return MergeFrom(data, extensionRegistry);
-      }
-      
-      public override IBuilder MergeFrom(pb::IMessage other) {
+      public override Builder MergeFrom(pb::IMessage other) {
         if (other is self::TestMessageSet) {
           return MergeFrom((self::TestMessageSet) other);
         } else {
@@ -239,17 +239,17 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
       }
       
-      public override IBuilder<self::TestMessageSet> MergeFrom(self::TestMessageSet other) {
+      public override Builder MergeFrom(self::TestMessageSet other) {
         if (other == self::TestMessageSet.DefaultInstance) return this;
         this.MergeUnknownFields(other.UnknownFields);
         return this;
       }
       
-      public override IBuilder<self::TestMessageSet> MergeFrom(pb::CodedInputStream input) {
+      public override Builder MergeFrom(pb::CodedInputStream input) {
         return MergeFrom(input, pb::ExtensionRegistry.Empty);
       }
       
-      public override IBuilder<self::TestMessageSet> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
         pb::UnknownFieldSet.Builder unknownFields =
           pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
         while (true) {
@@ -368,12 +368,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::TestMessageSetContainer> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::TestMessageSetContainer prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::GeneratedBuilder<self::TestMessageSetContainer, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::TestMessageSetContainer.CreateBuilder()
       internal Builder() {}
       
@@ -383,12 +387,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::TestMessageSetContainer> Clear() {
+      public override Builder Clear() {
         result = new self::TestMessageSetContainer();
         return this;
       }
       
-      public override IBuilder<self::TestMessageSetContainer> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       
@@ -406,11 +410,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return returnMe;
       }
       
-      protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-        return MergeFrom(data, extensionRegistry);
-      }
-      
-      public override IBuilder MergeFrom(pb::IMessage other) {
+      public override Builder MergeFrom(pb::IMessage other) {
         if (other is self::TestMessageSetContainer) {
           return MergeFrom((self::TestMessageSetContainer) other);
         } else {
@@ -419,7 +419,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
       }
       
-      public override IBuilder<self::TestMessageSetContainer> MergeFrom(self::TestMessageSetContainer other) {
+      public override Builder MergeFrom(self::TestMessageSetContainer other) {
         if (other == self::TestMessageSetContainer.DefaultInstance) return this;
         if (other.HasMessageSet) {
           MergeMessageSet(other.MessageSet);
@@ -428,11 +428,11 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       
-      public override IBuilder<self::TestMessageSetContainer> MergeFrom(pb::CodedInputStream input) {
+      public override Builder MergeFrom(pb::CodedInputStream input) {
         return MergeFrom(input, pb::ExtensionRegistry.Empty);
       }
       
-      public override IBuilder<self::TestMessageSetContainer> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
         pb::UnknownFieldSet.Builder unknownFields =
           pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
         while (true) {
@@ -520,8 +520,8 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     #region Nested types
     public static class Types {
-      public static readonly pb::GeneratedExtensionBase<self::TestMessageSet, self::TestMessageSetExtension1> MessageSetExtension =
-            pb::GeneratedSingleExtension<self::TestMessageSet, self::TestMessageSetExtension1>.CreateInstance(Descriptor.Extensions[0]);
+      public static readonly pb::GeneratedExtensionBase<self::TestMessageSetExtension1> MessageSetExtension =
+            pb::GeneratedSingleExtension<self::TestMessageSetExtension1>.CreateInstance(Descriptor.Extensions[0]);
     }
     #endregion
     
@@ -599,12 +599,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::TestMessageSetExtension1> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::TestMessageSetExtension1 prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::GeneratedBuilder<self::TestMessageSetExtension1, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::TestMessageSetExtension1.CreateBuilder()
       internal Builder() {}
       
@@ -614,12 +618,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::TestMessageSetExtension1> Clear() {
+      public override Builder Clear() {
         result = new self::TestMessageSetExtension1();
         return this;
       }
       
-      public override IBuilder<self::TestMessageSetExtension1> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       
@@ -637,11 +641,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return returnMe;
       }
       
-      protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-        return MergeFrom(data, extensionRegistry);
-      }
-      
-      public override IBuilder MergeFrom(pb::IMessage other) {
+      public override Builder MergeFrom(pb::IMessage other) {
         if (other is self::TestMessageSetExtension1) {
           return MergeFrom((self::TestMessageSetExtension1) other);
         } else {
@@ -650,7 +650,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
       }
       
-      public override IBuilder<self::TestMessageSetExtension1> MergeFrom(self::TestMessageSetExtension1 other) {
+      public override Builder MergeFrom(self::TestMessageSetExtension1 other) {
         if (other == self::TestMessageSetExtension1.DefaultInstance) return this;
         if (other.HasI) {
           I = other.I;
@@ -659,11 +659,11 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       
-      public override IBuilder<self::TestMessageSetExtension1> MergeFrom(pb::CodedInputStream input) {
+      public override Builder MergeFrom(pb::CodedInputStream input) {
         return MergeFrom(input, pb::ExtensionRegistry.Empty);
       }
       
-      public override IBuilder<self::TestMessageSetExtension1> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
         pb::UnknownFieldSet.Builder unknownFields =
           pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
         while (true) {
@@ -730,8 +730,8 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     #region Nested types
     public static class Types {
-      public static readonly pb::GeneratedExtensionBase<self::TestMessageSet, self::TestMessageSetExtension2> MessageSetExtension =
-            pb::GeneratedSingleExtension<self::TestMessageSet, self::TestMessageSetExtension2>.CreateInstance(Descriptor.Extensions[0]);
+      public static readonly pb::GeneratedExtensionBase<self::TestMessageSetExtension2> MessageSetExtension =
+            pb::GeneratedSingleExtension<self::TestMessageSetExtension2>.CreateInstance(Descriptor.Extensions[0]);
     }
     #endregion
     
@@ -809,12 +809,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::TestMessageSetExtension2> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::TestMessageSetExtension2 prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::GeneratedBuilder<self::TestMessageSetExtension2, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::TestMessageSetExtension2.CreateBuilder()
       internal Builder() {}
       
@@ -824,12 +828,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::TestMessageSetExtension2> Clear() {
+      public override Builder Clear() {
         result = new self::TestMessageSetExtension2();
         return this;
       }
       
-      public override IBuilder<self::TestMessageSetExtension2> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       
@@ -847,11 +851,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return returnMe;
       }
       
-      protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-        return MergeFrom(data, extensionRegistry);
-      }
-      
-      public override IBuilder MergeFrom(pb::IMessage other) {
+      public override Builder MergeFrom(pb::IMessage other) {
         if (other is self::TestMessageSetExtension2) {
           return MergeFrom((self::TestMessageSetExtension2) other);
         } else {
@@ -860,7 +860,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
       }
       
-      public override IBuilder<self::TestMessageSetExtension2> MergeFrom(self::TestMessageSetExtension2 other) {
+      public override Builder MergeFrom(self::TestMessageSetExtension2 other) {
         if (other == self::TestMessageSetExtension2.DefaultInstance) return this;
         if (other.HasStr) {
           Str = other.Str;
@@ -869,11 +869,11 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       
-      public override IBuilder<self::TestMessageSetExtension2> MergeFrom(pb::CodedInputStream input) {
+      public override Builder MergeFrom(pb::CodedInputStream input) {
         return MergeFrom(input, pb::ExtensionRegistry.Empty);
       }
       
-      public override IBuilder<self::TestMessageSetExtension2> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
         pb::UnknownFieldSet.Builder unknownFields =
           pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
         while (true) {
@@ -1050,12 +1050,16 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
         
         public static Builder CreateBuilder() { return new Builder(); }
-        public override IBuilder<self::RawMessageSet.Types.Item> CreateBuilderForType() { return new Builder(); }
+        public override Builder CreateBuilderForType() { return new Builder(); }
         public static Builder CreateBuilder(self::RawMessageSet.Types.Item prototype) {
           return (Builder) new Builder().MergeFrom(prototype);
         }
         
         public sealed partial class Builder : pb::GeneratedBuilder<self::RawMessageSet.Types.Item, Builder> {
+          protected override Builder ThisBuilder {
+            get { return this; }
+          }
+          
           // Construct using self::RawMessageSet.Types.Item.CreateBuilder()
           internal Builder() {}
           
@@ -1065,12 +1069,12 @@ namespace Google.ProtocolBuffers.TestProtos {
             get { return result; }
           }
           
-          public override IBuilder<self::RawMessageSet.Types.Item> Clear() {
+          public override Builder Clear() {
             result = new self::RawMessageSet.Types.Item();
             return this;
           }
           
-          public override IBuilder<self::RawMessageSet.Types.Item> Clone() {
+          public override Builder Clone() {
             return new Builder().MergeFrom(result);
           }
           
@@ -1088,11 +1092,7 @@ namespace Google.ProtocolBuffers.TestProtos {
             return returnMe;
           }
           
-          protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-            return MergeFrom(data, extensionRegistry);
-          }
-          
-          public override IBuilder MergeFrom(pb::IMessage other) {
+          public override Builder MergeFrom(pb::IMessage other) {
             if (other is self::RawMessageSet.Types.Item) {
               return MergeFrom((self::RawMessageSet.Types.Item) other);
             } else {
@@ -1101,7 +1101,7 @@ namespace Google.ProtocolBuffers.TestProtos {
             }
           }
           
-          public override IBuilder<self::RawMessageSet.Types.Item> MergeFrom(self::RawMessageSet.Types.Item other) {
+          public override Builder MergeFrom(self::RawMessageSet.Types.Item other) {
             if (other == self::RawMessageSet.Types.Item.DefaultInstance) return this;
             if (other.HasTypeId) {
               TypeId = other.TypeId;
@@ -1113,11 +1113,11 @@ namespace Google.ProtocolBuffers.TestProtos {
             return this;
           }
           
-          public override IBuilder<self::RawMessageSet.Types.Item> MergeFrom(pb::CodedInputStream input) {
+          public override Builder MergeFrom(pb::CodedInputStream input) {
             return MergeFrom(input, pb::ExtensionRegistry.Empty);
           }
           
-          public override IBuilder<self::RawMessageSet.Types.Item> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+          public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
             pb::UnknownFieldSet.Builder unknownFields =
               pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
             while (true) {
@@ -1269,12 +1269,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::RawMessageSet> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::RawMessageSet prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::GeneratedBuilder<self::RawMessageSet, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::RawMessageSet.CreateBuilder()
       internal Builder() {}
       
@@ -1284,12 +1288,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::RawMessageSet> Clear() {
+      public override Builder Clear() {
         result = new self::RawMessageSet();
         return this;
       }
       
-      public override IBuilder<self::RawMessageSet> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       
@@ -1310,11 +1314,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         return returnMe;
       }
       
-      protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
-        return MergeFrom(data, extensionRegistry);
-      }
-      
-      public override IBuilder MergeFrom(pb::IMessage other) {
+      public override Builder MergeFrom(pb::IMessage other) {
         if (other is self::RawMessageSet) {
           return MergeFrom((self::RawMessageSet) other);
         } else {
@@ -1323,7 +1323,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         }
       }
       
-      public override IBuilder<self::RawMessageSet> MergeFrom(self::RawMessageSet other) {
+      public override Builder MergeFrom(self::RawMessageSet other) {
         if (other == self::RawMessageSet.DefaultInstance) return this;
         if (other.item_.Count != 0) {
           if (result.item_.Count == 0) {
@@ -1335,11 +1335,11 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       
-      public override IBuilder<self::RawMessageSet> MergeFrom(pb::CodedInputStream input) {
+      public override Builder MergeFrom(pb::CodedInputStream input) {
         return MergeFrom(input, pb::ExtensionRegistry.Empty);
       }
       
-      public override IBuilder<self::RawMessageSet> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
         pb::UnknownFieldSet.Builder unknownFields =
           pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
         while (true) {

+ 9 - 5
csharp/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs

@@ -77,8 +77,8 @@ namespace Google.ProtocolBuffers.TestProtos {
     
     #region Nested types
     public static class Types {
-      public static readonly pb::GeneratedExtensionBase<self::TestOptimizedForSize, int> TestExtension =
-            pb::GeneratedSingleExtension<self::TestOptimizedForSize, int>.CreateInstance(Descriptor.Extensions[0]);
+      public static readonly pb::GeneratedExtensionBase<int> TestExtension =
+            pb::GeneratedSingleExtension<int>.CreateInstance(Descriptor.Extensions[0]);
     }
     #endregion
     
@@ -137,12 +137,16 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     public static Builder CreateBuilder() { return new Builder(); }
-    public override IBuilder<self::TestOptimizedForSize> CreateBuilderForType() { return new Builder(); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
     public static Builder CreateBuilder(self::TestOptimizedForSize prototype) {
       return (Builder) new Builder().MergeFrom(prototype);
     }
     
     public sealed partial class Builder : pb::ExtendableBuilder<self::TestOptimizedForSize, self::TestOptimizedForSize.Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      
       // Construct using self::TestOptimizedForSize.CreateBuilder()
       internal Builder() {}
       
@@ -152,12 +156,12 @@ namespace Google.ProtocolBuffers.TestProtos {
         get { return result; }
       }
       
-      public override IBuilder<self::TestOptimizedForSize> Clear() {
+      public override Builder Clear() {
         result = new self::TestOptimizedForSize();
         return this;
       }
       
-      public override IBuilder<self::TestOptimizedForSize> Clone() {
+      public override Builder Clone() {
         return new Builder().MergeFrom(result);
       }
       

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 252 - 252
csharp/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs


+ 91 - 71
csharp/ProtocolBuffers/AbstractBuilder.cs

@@ -8,10 +8,16 @@ using System.IO;
 namespace Google.ProtocolBuffers {
   /// <summary>
   /// Implementation of the non-generic IMessage interface as far as possible.
-  /// TODO(jonskeet): Make this generic, to avoid so much casting in DynamicMessage.
   /// </summary>
-  public abstract class AbstractBuilder : IBuilder {
+  public abstract class AbstractBuilder<TMessage, TBuilder> : IBuilder<TMessage, TBuilder> 
+      where TMessage : AbstractMessage<TMessage, TBuilder>
+      where TBuilder : AbstractBuilder<TMessage, TBuilder> {
+
+    protected abstract TBuilder ThisBuilder { get; }
+    
     #region Unimplemented members of IBuilder
+    public abstract UnknownFieldSet UnknownFields { get; set; }
+    public abstract TBuilder MergeFrom(TMessage other);
     public abstract bool IsInitialized { get; }
     public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
     public abstract object this[FieldDescriptor field] { get; set; }
@@ -19,55 +25,75 @@ namespace Google.ProtocolBuffers {
     public abstract int GetRepeatedFieldCount(FieldDescriptor field);
     public abstract object this[FieldDescriptor field, int index] { get; set; }
     public abstract bool HasField(FieldDescriptor field);
+    public abstract TMessage Build();
+    public abstract TMessage BuildPartial();
+    public abstract TBuilder Clone();
+    public abstract TMessage DefaultInstanceForType { get; }
+    public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
+    public abstract TBuilder ClearField(FieldDescriptor field);
+    public abstract TBuilder AddRepeatedField(FieldDescriptor field, object value);
     #endregion
 
-    #region New abstract methods to be overridden by implementations, allow explicit interface implementation
-    protected abstract IMessage BuildImpl();
-    protected abstract IMessage BuildPartialImpl();
-    protected abstract IBuilder CloneImpl();
-    protected abstract IMessage DefaultInstanceForTypeImpl { get; }
-    protected abstract IBuilder ClearFieldImpl(FieldDescriptor field);
-    protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value);
-    #endregion
+    #region Implementation of methods which don't require type parameter information
+    public IMessage WeakBuild() {
+      return Build();
+    }
 
-    #region Methods simply proxying to the "Impl" methods, explicitly implementing IBuilder
-    IMessage IBuilder.Build() {
-      return BuildImpl();
+    public IBuilder WeakAddRepeatedField(FieldDescriptor field, object value) {
+      return AddRepeatedField(field, value);
     }
 
-    IMessage IBuilder.BuildPartial() {
-      return BuildPartialImpl();
+    public IBuilder WeakClear() {
+      return Clear();
     }
 
-    IBuilder IBuilder.Clone() {
-      return CloneImpl();
+    public IBuilder WeakMergeFrom(IMessage message) {
+      return MergeFrom(message);
     }
-    
-    IMessage IBuilder.DefaultInstanceForType {
-      get { return DefaultInstanceForTypeImpl; }
+
+    public IBuilder WeakMergeFrom(CodedInputStream input) {
+      return MergeFrom(input);
     }
 
-    public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
+    public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
+      return MergeFrom(input, registry);
+    }
+
+    public IBuilder WeakMergeFrom(ByteString data) {
+      return MergeFrom(data);
+    }
+
+    public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
+      return MergeFrom(data, registry);
+    }
 
-    IBuilder IBuilder.ClearField(FieldDescriptor field) {
-      return ClearFieldImpl(field);
+    public IMessage WeakBuildPartial() {
+      return BuildPartial();
     }
 
-    IBuilder IBuilder.AddRepeatedField(FieldDescriptor field, object value) {
-      return AddRepeatedFieldImpl(field, value);
+    public IBuilder WeakClone() {
+      return Clone();
+    }
+
+    public IMessage WeakDefaultInstanceForType {
+      get { return DefaultInstanceForType; } 
+    }
+
+    public IBuilder WeakClearField(FieldDescriptor field) {
+      return ClearField(field);
     }
     #endregion
 
-    public virtual IBuilder Clear() {
+    public virtual TBuilder Clear() {
       foreach(FieldDescriptor field in AllFields.Keys) {
-        ClearFieldImpl(field);
+        ClearField(field);
       }
-      return this;
+      return ThisBuilder;
     }
 
-    public virtual IBuilder MergeFrom(IMessage other) {
+    public virtual TBuilder MergeFrom(IMessage other) {
       if (other.DescriptorForType != DescriptorForType) {
-        throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
+        throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
       }
 
       // Note:  We don't attempt to verify that other's fields have valid
@@ -83,101 +109,95 @@ namespace Google.ProtocolBuffers {
         if (field.IsRepeated) {
           // Concatenate repeated fields
           foreach (object element in (IEnumerable) entry.Value) {
-            AddRepeatedFieldImpl(field, element);
+            AddRepeatedField(field, element);
           }
         } else if (field.MappedType == MappedType.Message) {
           // Merge singular messages
           IMessage existingValue = (IMessage) this[field];
-          if (existingValue == existingValue.DefaultInstanceForType) {
+          if (existingValue == existingValue.WeakDefaultInstanceForType) {
             this[field] = entry.Value;
           } else {
-            this[field] = existingValue.CreateBuilderForType()
-                                       .MergeFrom(existingValue)
-                                       .MergeFrom((IMessage) entry.Value)
-                                       .Build();
+            this[field] = existingValue.WeakCreateBuilderForType()
+                                       .WeakMergeFrom(existingValue)
+                                       .WeakMergeFrom((IMessage) entry.Value)
+                                       .WeakBuild();
           }
         } else {
           // Overwrite simple values
           this[field] = entry.Value;
         }
       }
-      return this;
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeFrom(CodedInputStream input) {
-      return MergeFromImpl(input, ExtensionRegistry.Empty);
+    public virtual TBuilder MergeFrom(CodedInputStream input) {
+      return MergeFrom(input, ExtensionRegistry.Empty);
     }
 
-    protected virtual IBuilder MergeFromImpl(CodedInputStream input, ExtensionRegistry extensionRegistry) {
+    public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
       UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
       FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
       UnknownFields = unknownFields.Build();
-      return this;
-    }
-
-    IBuilder IBuilder.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
-      return MergeFromImpl(input, extensionRegistry);
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeUnknownFields(UnknownFieldSet unknownFields) {
+    public virtual TBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
       UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
           .MergeFrom(unknownFields)
           .Build();
-      return this;
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeFrom(ByteString data) {
+    public virtual TBuilder MergeFrom(ByteString data) {
       CodedInputStream input = data.CreateCodedInput();
-      ((IBuilder)this).MergeFrom(input);
+      MergeFrom(input);
       input.CheckLastTagWas(0);
-      return this;
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
+    public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
       CodedInputStream input = data.CreateCodedInput();
-      ((IBuilder)this).MergeFrom(input, extensionRegistry);
+      MergeFrom(input, extensionRegistry);
       input.CheckLastTagWas(0);
-      return this;
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeFrom(byte[] data) {
+    public virtual TBuilder MergeFrom(byte[] data) {
       CodedInputStream input = CodedInputStream.CreateInstance(data);
-      ((IBuilder)this).MergeFrom(input);
+      MergeFrom(input);
       input.CheckLastTagWas(0);
-      return this;
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
+    public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
       CodedInputStream input = CodedInputStream.CreateInstance(data);
-      ((IBuilder)this).MergeFrom(input, extensionRegistry);
+      MergeFrom(input, extensionRegistry);
       input.CheckLastTagWas(0);
-      return this;
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeFrom(Stream input) {
+    public virtual TBuilder MergeFrom(Stream input) {
       CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
-      ((IBuilder)this).MergeFrom(codedInput);
+      MergeFrom(codedInput);
       codedInput.CheckLastTagWas(0);
-      return this;
+      return ThisBuilder;
     }
 
-    IBuilder IBuilder.MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
+    public virtual TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
       CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
-      ((IBuilder)this).MergeFrom(codedInput, extensionRegistry);
+      MergeFrom(codedInput, extensionRegistry);
       codedInput.CheckLastTagWas(0);
-      return this;
+      return ThisBuilder;
     }
 
-    public abstract UnknownFieldSet UnknownFields { get; set; }
-    
-    public IBuilder SetField(FieldDescriptor field, object value) {
+    public virtual IBuilder SetField(FieldDescriptor field, object value) {
       this[field] = value;
-      return this;
+      return ThisBuilder;
     }
 
-    public IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) {
+    public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) {
       this[field, index] = value;
-      return this;
+      return ThisBuilder;
     }
   }
 }

+ 13 - 15
csharp/ProtocolBuffers/AbstractMessage.cs

@@ -23,7 +23,9 @@ namespace Google.ProtocolBuffers {
   /// <summary>
   /// Implementation of the non-generic IMessage interface as far as possible.
   /// </summary>
-  public abstract class AbstractMessage : IMessage {
+  public abstract class AbstractMessage<TMessage, TBuilder> : IMessage<TMessage, TBuilder> 
+      where TMessage : AbstractMessage<TMessage, TBuilder> 
+      where TBuilder : AbstractBuilder<TMessage, TBuilder> {
     // TODO(jonskeet): Cleaner to use a Nullable<int>?
     /// <summary>
     /// The serialized size if it's already been computed, or -1
@@ -39,21 +41,17 @@ namespace Google.ProtocolBuffers {
     public abstract int GetRepeatedFieldCount(FieldDescriptor field);
     public abstract object this[FieldDescriptor field, int index] { get; }
     public abstract UnknownFieldSet UnknownFields { get; }
+    public abstract TMessage DefaultInstanceForType { get; }
+    public abstract TBuilder CreateBuilderForType();
     #endregion
-
-    #region New abstract methods to be overridden by implementations, allow explicit interface implementation
-    protected abstract IMessage DefaultInstanceForTypeImpl { get; }
-    protected abstract IBuilder CreateBuilderForTypeImpl();
-    #endregion
-
-    #region Methods simply proxying to the "Impl" methods, explicitly implementing IMessage
-    IMessage IMessage.DefaultInstanceForType { 
-      get { return DefaultInstanceForTypeImpl; }
+    
+    public IBuilder WeakCreateBuilderForType() {
+      return CreateBuilderForType();
     }
-    IBuilder IMessage.CreateBuilderForType() { 
-      return CreateBuilderForTypeImpl(); 
+
+    public IMessage WeakDefaultInstanceForType {
+      get { return DefaultInstanceForType; }
     }
-    #endregion
 
     public virtual bool IsInitialized {
       get {
@@ -71,7 +69,7 @@ namespace Google.ProtocolBuffers {
             if (field.IsRepeated) {
               // We know it's an IList<T>, but not the exact type - so
               // IEnumerable is the best we can do. (C# generics aren't covariant yet.)
-              foreach (IMessage element in (IEnumerable)entry.Value) {
+              foreach (IMessage element in (IEnumerable) entry.Value) {
                 if (!element.IsInitialized) {
                   return false;
                 }
@@ -124,7 +122,7 @@ namespace Google.ProtocolBuffers {
         foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
           FieldDescriptor field = entry.Key;
           if (field.IsRepeated) {
-            foreach (object element in (IEnumerable)entry.Value) {
+            foreach (object element in (IEnumerable) entry.Value) {
               size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, element);
             }
           } else {

+ 2 - 2
csharp/ProtocolBuffers/CodedInputStream.cs

@@ -224,7 +224,7 @@ namespace Google.ProtocolBuffers {
         throw InvalidProtocolBufferException.RecursionLimitExceeded();
       }
       ++recursionDepth;
-      builder.MergeFrom(this, extensionRegistry);
+      builder.WeakMergeFrom(this, extensionRegistry);
       CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
       --recursionDepth;
     }
@@ -253,7 +253,7 @@ namespace Google.ProtocolBuffers {
       }
       int oldLimit = PushLimit(length);
       ++recursionDepth;
-      builder.MergeFrom(this, extensionRegistry);
+      builder.WeakMergeFrom(this, extensionRegistry);
       CheckLastTagWas(0);
       --recursionDepth;
       PopLimit(oldLimit);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 162 - 162
csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs


+ 43 - 35
csharp/ProtocolBuffers/DynamicMessage.cs

@@ -10,7 +10,7 @@ namespace Google.ProtocolBuffers {
   /// An implementation of IMessage that can represent arbitrary types, given a MessageaDescriptor.
   /// TODO: Implement appropriate generics.
   /// </summary>
-  public class DynamicMessage : AbstractMessage {
+  public class DynamicMessage : AbstractMessage<DynamicMessage, DynamicMessage.Builder> {
 
     private readonly MessageDescriptor type;
     private readonly FieldSet fields;
@@ -42,8 +42,8 @@ namespace Google.ProtocolBuffers {
     /// Parses a message of the given type from the given stream.
     /// </summary>
     public static DynamicMessage ParseFrom(MessageDescriptor type, CodedInputStream input) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder)builder.MergeFrom(input);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(input);
       return dynamicBuilder.BuildParsed();
 
     }
@@ -56,8 +56,8 @@ namespace Google.ProtocolBuffers {
     /// <param name="extensionRegistry"></param>
     /// <returns></returns>
     public static DynamicMessage ParseFrom(MessageDescriptor type, CodedInputStream input, ExtensionRegistry extensionRegistry) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder) builder.MergeFrom(input, extensionRegistry);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(input, extensionRegistry);
       return dynamicBuilder.BuildParsed();
     }
 
@@ -65,8 +65,8 @@ namespace Google.ProtocolBuffers {
     /// Parses a message of the given type from the given stream.
     /// </summary>
     public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder)builder.MergeFrom(input);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(input);
       return dynamicBuilder.BuildParsed();
     }
 
@@ -78,8 +78,8 @@ namespace Google.ProtocolBuffers {
     /// <param name="extensionRegistry"></param>
     /// <returns></returns>
     public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input, ExtensionRegistry extensionRegistry) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder)builder.MergeFrom(input, extensionRegistry);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(input, extensionRegistry);
       return dynamicBuilder.BuildParsed();
     }
 
@@ -87,8 +87,8 @@ namespace Google.ProtocolBuffers {
     /// Parse <paramref name="data"/> as a message of the given type and return it.
     /// </summary>
     public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder)builder.MergeFrom(data);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(data);
       return dynamicBuilder.BuildParsed();
     }
 
@@ -96,8 +96,8 @@ namespace Google.ProtocolBuffers {
     /// Parse <paramref name="data"/> as a message of the given type and return it.
     /// </summary>
     public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data, ExtensionRegistry extensionRegistry) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder)builder.MergeFrom(data, extensionRegistry);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(data, extensionRegistry);
       return dynamicBuilder.BuildParsed();
 
     }
@@ -106,8 +106,8 @@ namespace Google.ProtocolBuffers {
     /// Parse <paramref name="data"/> as a message of the given type and return it.
     /// </summary>
     public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder)builder.MergeFrom(data);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(data);
       return dynamicBuilder.BuildParsed();
     }
 
@@ -115,8 +115,8 @@ namespace Google.ProtocolBuffers {
     /// Parse <paramref name="data"/> as a message of the given type and return it.
     /// </summary>
     public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data, ExtensionRegistry extensionRegistry) {
-      IBuilder builder = CreateBuilder(type);
-      Builder dynamicBuilder = (Builder)builder.MergeFrom(data, extensionRegistry);
+      Builder builder = CreateBuilder(type);
+      Builder dynamicBuilder = builder.MergeFrom(data, extensionRegistry);
       return dynamicBuilder.BuildParsed();
     }
 
@@ -134,7 +134,7 @@ namespace Google.ProtocolBuffers {
     /// <param name="prototype"></param>
     /// <returns></returns>
     public static Builder CreateBuilder(IMessage prototype) {
-      return (Builder) new Builder(prototype.DescriptorForType).MergeFrom(prototype);
+      return new Builder(prototype.DescriptorForType).MergeFrom(prototype);
     }
 
     // -----------------------------------------------------------------
@@ -144,7 +144,7 @@ namespace Google.ProtocolBuffers {
       get { return type; }
     }
 
-    protected override IMessage DefaultInstanceForTypeImpl {
+    public override DynamicMessage DefaultInstanceForType {
       get { return GetDefaultInstance(type); }
     }
 
@@ -214,7 +214,7 @@ namespace Google.ProtocolBuffers {
       }
     }
 
-    protected override IBuilder CreateBuilderForTypeImpl() {
+    public override Builder CreateBuilderForType() {
       return new Builder(type);
     }
 
@@ -227,7 +227,7 @@ namespace Google.ProtocolBuffers {
       }
     }
 
-    public class Builder : AbstractBuilder {
+    public class Builder : AbstractBuilder<DynamicMessage, DynamicMessage.Builder> {
       private readonly MessageDescriptor type;
       private FieldSet fields;
       private UnknownFieldSet unknownFields;
@@ -238,16 +238,16 @@ namespace Google.ProtocolBuffers {
         this.unknownFields = UnknownFieldSet.DefaultInstance;
       }
 
-      public DynamicMessage Build() {
-        return (DynamicMessage)((IBuilder)this).Build();
+      protected override Builder ThisBuilder {
+        get { return this; }
       }
 
-      public override IBuilder Clear() {
+      public override Builder Clear() {
         fields.Clear();
         return this;
       }
 
-      public override IBuilder MergeFrom(IMessage other) {
+      public override Builder MergeFrom(IMessage other) {
         if (other.DescriptorForType != type) {
           throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
         }
@@ -255,11 +255,19 @@ namespace Google.ProtocolBuffers {
         return this;
       }
 
-      protected override IMessage BuildImpl() {
+      public override Builder MergeFrom(DynamicMessage other) {
+        if (other.DescriptorForType != type) {
+          throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
+        }
+        fields.MergeFrom(other);
+        return this;
+      }
+
+      public override DynamicMessage Build() {
    	    if (!IsInitialized) {
           throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields));
         }
-        return BuildPartialImpl();
+        return BuildPartial();
       }
 
       /// <summary>
@@ -271,10 +279,10 @@ namespace Google.ProtocolBuffers {
         if (!IsInitialized) {
           throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)).AsInvalidProtocolBufferException();
         }
-        return (DynamicMessage) BuildPartialImpl();
+        return BuildPartial();
       }
 
-      protected override IMessage BuildPartialImpl() {
+      public override DynamicMessage BuildPartial() {
         fields.MakeImmutable();
         DynamicMessage result = new DynamicMessage(type, fields, unknownFields);
         fields = null;
@@ -282,7 +290,7 @@ namespace Google.ProtocolBuffers {
         return result;
       }
 
-      protected override IBuilder CloneImpl() {
+      public override Builder Clone() {
         Builder result = new Builder(type);
         result.fields.MergeFrom(fields);
         return result;
@@ -292,7 +300,7 @@ namespace Google.ProtocolBuffers {
       	get { return fields.IsInitializedWithRespectTo(type); }
       }
 
-      protected override IBuilder MergeFromImpl(CodedInputStream input, ExtensionRegistry extensionRegistry) {
+      public override Builder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
         UnknownFieldSet.Builder unknownFieldsBuilder = UnknownFieldSet.CreateBuilder(unknownFields);
         FieldSet.MergeFrom(input, unknownFieldsBuilder, extensionRegistry, this);
         unknownFields = unknownFieldsBuilder.Build();
@@ -303,7 +311,7 @@ namespace Google.ProtocolBuffers {
         get { return type; }
       }
 
-      protected override IMessage DefaultInstanceForTypeImpl {
+      public override DynamicMessage DefaultInstanceForType {
         get { return GetDefaultInstance(type); }
       }
 
@@ -316,7 +324,7 @@ namespace Google.ProtocolBuffers {
         if (field.MappedType != MappedType.Message) {
           throw new ArgumentException("CreateBuilderForField is only valid for fields with message type.");
         }
-        return new Builder(field.MessageType);        
+        return new Builder(field.MessageType);     
       }
 
       public override bool HasField(FieldDescriptor field) {
@@ -350,7 +358,7 @@ namespace Google.ProtocolBuffers {
         }
       }
 
-      protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
+      public override Builder ClearField(FieldDescriptor field) {
         VerifyContainingType(field);
         fields.ClearField(field);
         return this;
@@ -361,7 +369,7 @@ namespace Google.ProtocolBuffers {
         return fields.GetRepeatedFieldCount(field);
       }
 
-      protected override IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value) {
+      public override Builder AddRepeatedField(FieldDescriptor field, object value) {
         VerifyContainingType(field);
         fields.AddRepeatedField(field, value);
         return this;

+ 14 - 17
csharp/ProtocolBuffers/ExtendableBuilder.cs

@@ -13,57 +13,55 @@ namespace Google.ProtocolBuffers {
     /// <summary>
     /// Checks if a singular extension is present
     /// </summary>
-    public bool HasExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
+    public bool HasExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
       return MessageBeingBuilt.HasExtension(extension);
     }
 
     /// <summary>
     /// Returns the number of elements in a repeated extension.
     /// </summary>
-    public int GetExtensionCount<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension) {
+    public int GetExtensionCount<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension) {
       return MessageBeingBuilt.GetExtensionCount(extension);
     }
 
     /// <summary>
     /// Returns the value of an extension.
     /// </summary>
-    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
+    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
       return MessageBeingBuilt.GetExtension(extension);
     }
 
     /// <summary>
     /// Returns one element of a repeated extension.
     /// </summary>
-    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index) {
+    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index) {
       return MessageBeingBuilt.GetExtension(extension, index);
     }
 
     /// <summary>
     /// Sets the value of an extension.
     /// </summary>
-    public ExtendableBuilder<TMessage, TBuilder> SetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension, TExtension value) {
+    public TBuilder SetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension, TExtension value) {
       ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
       message.VerifyExtensionContainingType(extension);
       message.Extensions[extension.Descriptor] = extension.ToReflectionType(value);
-      return this;
+      return ThisBuilder;
     }
 
     /// <summary>
     /// Sets the value of one element of a repeated extension.
     /// </summary>
-    public ExtendableBuilder<TMessage, TBuilder> SetExtension<TExtension>(
-        GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index, TExtension value) {
+    public TBuilder SetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index, TExtension value) {
       ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
       message.VerifyExtensionContainingType(extension);
       message.Extensions[extension.Descriptor, index] = extension.SingularToReflectionType(value);
-      return this;
+      return ThisBuilder;
     }
 
     /// <summary>
     /// Appends a value to a repeated extension.
     /// </summary>
-    public ExtendableBuilder<TMessage, TBuilder> AddExtension<TExtension>(
-        GeneratedExtensionBase<TMessage, IList<TExtension>> extension, TExtension value) {
+    public ExtendableBuilder<TMessage, TBuilder> AddExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, TExtension value) {
       ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
       message.VerifyExtensionContainingType(extension);
       message.Extensions.AddRepeatedField(extension.Descriptor, extension.SingularToReflectionType(value));
@@ -73,8 +71,7 @@ namespace Google.ProtocolBuffers {
     /// <summary>
     /// Clears an extension.
     /// </summary>
-    public ExtendableBuilder<TMessage, TBuilder> ClearExtension<TExtension>(
-        GeneratedExtensionBase<TMessage, TExtension> extension) {
+    public ExtendableBuilder<TMessage, TBuilder> ClearExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
       ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
       message.VerifyExtensionContainingType(extension);
       message.Extensions.ClearField(extension.Descriptor);
@@ -121,23 +118,23 @@ namespace Google.ProtocolBuffers {
       }
     }
 
-    public override IBuilder<TMessage> ClearField(FieldDescriptor field) {
+    public override TBuilder ClearField(FieldDescriptor field) {
       if (field.IsExtension) {
         ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
         message.VerifyContainingType(field);
         message.Extensions.ClearField(field);
-        return this;
+        return ThisBuilder;
       } else {
         return base.ClearField(field);
       }
     }
 
-    public override IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
+    public override TBuilder AddRepeatedField(FieldDescriptor field, object value) {
       if (field.IsExtension) {
         ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
         message.VerifyContainingType(field); 
         message.Extensions.AddRepeatedField(field, value);
-        return this;
+        return ThisBuilder;
       } else {
         return base.AddRepeatedField(field, value);
       }

+ 7 - 7
csharp/ProtocolBuffers/ExtendableMessage.cs

@@ -5,9 +5,9 @@ using Google.ProtocolBuffers.Descriptors;
 using Google.ProtocolBuffers.Collections;
 
 namespace Google.ProtocolBuffers {
-  public abstract class ExtendableMessage<TMessage,TBuilder> : GeneratedMessage<TMessage,TBuilder>
+  public abstract class ExtendableMessage<TMessage, TBuilder> : GeneratedMessage<TMessage, TBuilder>
     where TMessage : GeneratedMessage<TMessage, TBuilder>
-    where TBuilder : IBuilder<TMessage> {
+    where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
 
     protected ExtendableMessage() {}
     private readonly FieldSet extensions = FieldSet.CreateFieldSet();
@@ -22,21 +22,21 @@ namespace Google.ProtocolBuffers {
     /// <summary>
     /// Checks if a singular extension is present.
     /// </summary>
-    public bool HasExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
+    public bool HasExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
       return extensions.HasField(extension.Descriptor);
     }
 
     /// <summary>
     /// Returns the number of elements in a repeated extension.
     /// </summary>
-    public int GetExtensionCount<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension) {
+    public int GetExtensionCount<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension) {
       return extensions.GetRepeatedFieldCount(extension.Descriptor);
     }
 
     /// <summary>
     /// Returns the value of an extension.
     /// </summary>
-    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
+    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
       object value = extensions[extension.Descriptor];
       if (value == null) {
         return (TExtension) extension.MessageDefaultInstance;
@@ -48,7 +48,7 @@ namespace Google.ProtocolBuffers {
     /// <summary>
     /// Returns one element of a repeated extension.
     /// </summary>
-    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index) {
+    public TExtension GetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index) {
       return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
     }
 
@@ -169,7 +169,7 @@ namespace Google.ProtocolBuffers {
       get { return extensions.SerializedSize; }
     }
 
-    internal void VerifyExtensionContainingType<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
+    internal void VerifyExtensionContainingType<TExtension>(GeneratedExtensionBase<TExtension> extension) {
       if (extension.Descriptor.ContainingType != DescriptorForType) {
         // This can only happen if someone uses unchecked operations.
         throw new ArgumentException("Extension is for type \"" + extension.Descriptor.ContainingType.FullName

+ 1 - 2
csharp/ProtocolBuffers/ExtensionRegistry.cs

@@ -88,8 +88,7 @@ namespace Google.ProtocolBuffers {
     /// <summary>
     /// Add an extension from a generated file to the registry.
     /// </summary>
-    public void Add<TContainer, TExtension> (GeneratedExtensionBase<TContainer, TExtension> extension) 
-        where TContainer : IMessage<TContainer> {
+    public void Add<TExtension> (GeneratedExtensionBase<TExtension> extension) {
       if (extension.Descriptor.MappedType == MappedType.Message) {
         Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance));
       } else {

+ 1 - 1
csharp/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs

@@ -40,7 +40,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
 
       // No... so let's create a builder of the right type, and merge the value in.
       IMessage message = (IMessage) value;
-      return CreateBuilder().MergeFrom(message).Build();
+      return CreateBuilder().WeakMergeFrom(message).WeakBuild();
     }
 
     public override void SetRepeated(IBuilder builder, int index, object value) {

+ 1 - 1
csharp/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs

@@ -38,7 +38,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
       
       // No... so let's create a builder of the right type, and merge the value in.
       IMessage message = (IMessage) value;
-      return CreateBuilder().MergeFrom(message).Build();
+      return CreateBuilder().WeakMergeFrom(message).WeakBuild();
     }
 
     public override void SetValue(IBuilder builder, object value) {

+ 14 - 14
csharp/ProtocolBuffers/FieldSet.cs

@@ -154,19 +154,19 @@ namespace Google.ProtocolBuffers {
         case FieldType.Message: {
             IBuilder subBuilder;
             if (defaultFieldInstance != null) {
-              subBuilder = defaultFieldInstance.CreateBuilderForType();
+              subBuilder = defaultFieldInstance.WeakCreateBuilderForType();
             } else {
               subBuilder = builder.CreateBuilderForField(field);
             }
             if (!field.IsRepeated) {
-              subBuilder.MergeFrom((IMessage) builder[field]);
+              subBuilder.WeakMergeFrom((IMessage) builder[field]);
             }
             if (field.FieldType == FieldType.Group) {
               input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
             } else {
               input.ReadMessage(subBuilder, extensionRegistry);
             }
-            value = subBuilder.Build();
+            value = subBuilder.WeakBuild();
             break;
           }
         case FieldType.Enum: {
@@ -185,7 +185,7 @@ namespace Google.ProtocolBuffers {
           break;
       }
       if (field.IsRepeated) {
-        builder.AddRepeatedField(field, value);
+        builder.WeakAddRepeatedField(field, value);
       } else {
         builder[field] = value;
       } 
@@ -236,16 +236,16 @@ namespace Google.ProtocolBuffers {
             ExtensionInfo extension = extensionRegistry[type, typeId];
             if (extension != null) {
               field = extension.Descriptor;
-              subBuilder = extension.DefaultInstance.CreateBuilderForType();
+              subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
               IMessage originalMessage = (IMessage) builder[field];
               if (originalMessage != null) {
-                subBuilder.MergeFrom(originalMessage);
+                subBuilder.WeakMergeFrom(originalMessage);
               }
               if (rawBytes != null) {
                 // We already encountered the message.  Parse it now.
                 // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
                 // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
-                subBuilder.MergeFrom(rawBytes.CreateCodedInput());
+                subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput());
                 rawBytes = null;
               }
             } else {
@@ -286,7 +286,7 @@ namespace Google.ProtocolBuffers {
       input.CheckLastTagWas(WireFormat.MessageSetTag.ItemEnd);
 
       if (subBuilder != null) {
-        builder[field] = subBuilder.Build();
+        builder[field] = subBuilder.WeakBuild();
       }
     }
 
@@ -381,7 +381,7 @@ namespace Google.ProtocolBuffers {
     }
 
     /// <summary>
-    /// See <see cref="IBuilder.AddRepeatedField" />
+    /// See <see cref="IBuilder{TMessage, TBuilder}.AddRepeatedField" />
     /// </summary>
     internal void AddRepeatedField(FieldDescriptor field, object value) {
       if (!field.IsRepeated) {
@@ -449,7 +449,7 @@ namespace Google.ProtocolBuffers {
     }
 
     /// <summary>
-    /// See <see cref="IBuilder.ClearField" />
+    /// See <see cref="IBuilder{TMessage, TBuilder}.ClearField" />
     /// </summary>
     public void ClearField(FieldDescriptor field) {
       fields.Remove(field);
@@ -495,10 +495,10 @@ namespace Google.ProtocolBuffers {
           }
         } else if (field.MappedType == MappedType.Message && existingValue != null) {
           IMessage existingMessage = (IMessage)existingValue;
-          IMessage merged = existingMessage.CreateBuilderForType()
-              .MergeFrom(existingMessage)
-              .MergeFrom((IMessage)entry.Value)
-              .Build();
+          IMessage merged = existingMessage.WeakCreateBuilderForType()
+              .WeakMergeFrom(existingMessage)
+              .WeakMergeFrom((IMessage) entry.Value)
+              .WeakBuild();
           this[field] = merged;
         } else {
           this[field] = entry.Value;

+ 17 - 95
csharp/ProtocolBuffers/GeneratedBuilder.cs

@@ -13,9 +13,9 @@ namespace Google.ProtocolBuffers {
   /// most of the IBuilder interface using reflection. Users can ignore this class
   /// as an implementation detail.
   /// </summary>
-  public abstract class GeneratedBuilder<TMessage, TBuilder> : AbstractBuilder, IBuilder<TMessage>
+  public abstract class GeneratedBuilder<TMessage, TBuilder> : AbstractBuilder<TMessage, TBuilder>
       where TMessage : GeneratedMessage <TMessage, TBuilder>
-      where TBuilder : GeneratedBuilder<TMessage, TBuilder>, IBuilder<TMessage> {
+      where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
 
     /// <summary>
     /// Returns the message being built at the moment.
@@ -43,7 +43,7 @@ namespace Google.ProtocolBuffers {
           : MessageBeingBuilt[field];
       }
       set {
-        InternalFieldAccessors[field].SetValue(this, value);
+        InternalFieldAccessors[field].SetValue(ThisBuilder, value);
       }
     }
 
@@ -87,40 +87,16 @@ namespace Google.ProtocolBuffers {
       return MessageBeingBuilt.HasField(field);
     }
 
-    protected override IMessage BuildImpl() {
-      return Build();
-    }
-
-    protected override IMessage BuildPartialImpl() {
-      return BuildPartial();
-    }
-
-    protected override IBuilder CloneImpl() {
-      return Clone();
-    }
-
-    protected override IMessage DefaultInstanceForTypeImpl {
-      get { return DefaultInstanceForType; }
-    }
-
     public override IBuilder CreateBuilderForField(FieldDescriptor field) {
       return InternalFieldAccessors[field].CreateBuilder();
     }
 
-    protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
-      return ClearField(field);
-    }
-
-    protected override IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value) {
-      return AddRepeatedField(field, value);
-    }
-
-    public virtual IBuilder<TMessage> ClearField(FieldDescriptor field) {
+    public override TBuilder ClearField(FieldDescriptor field) {
       InternalFieldAccessors[field].Clear(this);
-      return this;
+      return ThisBuilder;
     }
 
-    public virtual IBuilder<TMessage> MergeFrom(TMessage other) {
+    public override TBuilder MergeFrom(TMessage other) {
       if (other.DescriptorForType != InternalFieldAccessors.Descriptor) {
         throw new ArgumentException("Message type mismatch");
       }
@@ -135,77 +111,31 @@ namespace Google.ProtocolBuffers {
         } else if (field.MappedType == MappedType.Message && HasField(field)) {
           // Merge singular embedded messages
           IMessage oldValue = (IMessage)this[field];
-          this[field] = oldValue.CreateBuilderForType()
-              .MergeFrom(oldValue)
-              .MergeFrom((IMessage)entry.Value)
-              .BuildPartial();
+          this[field] = oldValue.WeakCreateBuilderForType()
+              .WeakMergeFrom(oldValue)
+              .WeakMergeFrom((IMessage)entry.Value)
+              .WeakBuildPartial();
         } else {
           // Just overwrite
           this[field] = entry.Value;
         }
       }
-      return this;
+      return ThisBuilder;
     }
 
-    public virtual IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) {
+    public override TBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
       TMessage result = MessageBeingBuilt;
       result.SetUnknownFields(UnknownFieldSet.CreateBuilder(result.UnknownFields)
           .MergeFrom(unknownFields)
           .Build());
-      return this;
+      return ThisBuilder;
     }
 
-    public virtual IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
+    public override TBuilder AddRepeatedField(FieldDescriptor field, object value) {
       InternalFieldAccessors[field].AddRepeated(this, value);
-      return this;
-    }
-
-    public IBuilder<TMessage> MergeFrom(ByteString data) {
-      ((IBuilder) this).MergeFrom(data);
-      return this;
-    }
-
-    public IBuilder<TMessage> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
-      ((IBuilder) this).MergeFrom(data, extensionRegistry);
-      return this;
-    }
-
-    public IBuilder<TMessage> MergeFrom(byte[] data) {
-      ((IBuilder) this).MergeFrom(data);
-      return this;
-    }
-
-    public IBuilder<TMessage> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
-      ((IBuilder) this).MergeFrom(data, extensionRegistry);
-      return this;
-    }
-
-    public IBuilder<TMessage> MergeFrom(Stream input) {
-      ((IBuilder) this).MergeFrom(input);
-      return this;
-    }
-
-    public IBuilder<TMessage> MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
-      ((IBuilder) this).MergeFrom(input, extensionRegistry);
-      return this;
+      return ThisBuilder;
     }
 
-    /// <summary>
-    /// Overridden when optimized for speed.
-    /// </summary>
-    public virtual IBuilder<TMessage> MergeFrom(CodedInputStream input) {
-      ((IBuilder)this).MergeFrom(input);
-      return this;
-    }
-
-    /// <summary>
-    /// Overridden when optimized for speed.
-    /// </summary>
-    public virtual IBuilder<TMessage> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
-      ((IBuilder)this).MergeFrom(input, extensionRegistry);
-      return this;
-    }
-    
     /// <summary>
     /// Like Build(), but will wrap UninitializedMessageException in
     /// InvalidProtocolBufferException.
@@ -219,10 +149,10 @@ namespace Google.ProtocolBuffers {
     }
 
     /// <summary>
-    /// Implementation of <see cref="IBuilder{T}.Build" />.
+    /// Implementation of <see cref="IBuilder{TMessage, TBuilder}.Build" />.
     /// TODO(jonskeet): This used to be generated for each class. Find out why.
     /// </summary>
-    public TMessage Build() {
+    public override TMessage Build() {
       if (!IsInitialized) {
         throw new UninitializedMessageException(MessageBeingBuilt);
       }
@@ -233,13 +163,5 @@ namespace Google.ProtocolBuffers {
       get { return MessageBeingBuilt.UnknownFields; }
       set { MessageBeingBuilt.SetUnknownFields(value); }
     }
-    
-    public abstract TMessage BuildPartial();
-    public abstract IBuilder<TMessage> Clone();
-    public abstract new IBuilder<TMessage> Clear();
-    public abstract TMessage DefaultInstanceForType { get; }
-    
-    public abstract class ExtendableBuilder : GeneratedBuilder<TMessage, TBuilder> {
-    }
   }
 }

+ 3 - 3
csharp/ProtocolBuffers/GeneratedExtensionBase.cs

@@ -29,7 +29,7 @@ namespace Google.ProtocolBuffers {
   /// The interface implemented by both GeneratedException and GeneratedRepeatException,
   /// to make it easier to cope with repeats separately.
   /// </remarks>
-  public abstract class GeneratedExtensionBase<TContainer, TExtension> {
+  public abstract class GeneratedExtensionBase<TExtension> {
 
     private readonly FieldDescriptor descriptor;
     private readonly IMessage messageDefaultInstance;
@@ -73,8 +73,8 @@ namespace Google.ProtocolBuffers {
             // GeneratedExtension manually and gives it a different type.
             // This should not happen in normal use.  But, to be nice, we'll
             // copy the message to whatever type the caller was expecting.
-            return MessageDefaultInstance.CreateBuilderForType()
-                           .MergeFrom((IMessage)value).Build();
+            return MessageDefaultInstance.WeakCreateBuilderForType()
+                           .WeakMergeFrom((IMessage)value).WeakBuild();
           }
         case MappedType.Enum:
           // Just return a boxed int - that can be unboxed to the enum

+ 2 - 14
csharp/ProtocolBuffers/GeneratedMessage.cs

@@ -13,9 +13,9 @@ namespace Google.ProtocolBuffers {
   /// most of the IMessage interface using reflection. Users
   /// can ignore this class as an implementation detail.
   /// </summary>
-  public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage, IMessage<TMessage>
+  public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage<TMessage, TBuilder>
       where TMessage : GeneratedMessage<TMessage, TBuilder> 
-      where TBuilder : IBuilder<TMessage> {
+      where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
 
     private UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
 
@@ -29,18 +29,6 @@ namespace Google.ProtocolBuffers {
       get { return InternalFieldAccessors.Descriptor; }
     }
 
-    protected override IMessage DefaultInstanceForTypeImpl {
-      get { return DefaultInstanceForType; }
-    }
-
-    protected override IBuilder CreateBuilderForTypeImpl() {
-      return CreateBuilderForType();
-    }
-
-    public abstract TMessage DefaultInstanceForType { get; }
-
-    public abstract IBuilder<TMessage> CreateBuilderForType();
-
     internal IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
 
       // Use a SortedList so we'll end up serializing fields in order

+ 3 - 3
csharp/ProtocolBuffers/GeneratedRepeatException.cs

@@ -7,15 +7,15 @@ namespace Google.ProtocolBuffers {
   /// <summary>
   /// Class used to represent repeat extensions in generated classes.
   /// </summary>
-  public class GeneratedRepeatExtension<TContainer, TExtensionElement> : GeneratedExtensionBase<TContainer, IList<TExtensionElement>> {
+  public class GeneratedRepeatExtension<TExtensionElement> : GeneratedExtensionBase<IList<TExtensionElement>> {
     private GeneratedRepeatExtension(FieldDescriptor field) : base(field, typeof(TExtensionElement)) {
     }
 
-    public static GeneratedExtensionBase<TContainer, IList<TExtensionElement>> CreateInstance(FieldDescriptor descriptor) {
+    public static GeneratedExtensionBase<IList<TExtensionElement>> CreateInstance(FieldDescriptor descriptor) {
       if (!descriptor.IsRepeated) {
         throw new ArgumentException("Must call GeneratedRepeatExtension.CreateInstance() for repeated types.");
       }
-      return new GeneratedRepeatExtension<TContainer, TExtensionElement>(descriptor);
+      return new GeneratedRepeatExtension<TExtensionElement>(descriptor);
     }
 
     /// <summary>

+ 3 - 5
csharp/ProtocolBuffers/GeneratedSingleExtension.cs

@@ -6,17 +6,15 @@ namespace Google.ProtocolBuffers {
   /// <summary>
   /// Generated extension for a singular field.
   /// </remarks>
-  public class GeneratedSingleExtension<TContainer, TExtension> : GeneratedExtensionBase<TContainer, TExtension>    
-      where TContainer : IMessage<TContainer> {
-
+  public class GeneratedSingleExtension<TExtension> : GeneratedExtensionBase<TExtension>  {
     internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor, typeof(TExtension)) {
     }
 
-    public static GeneratedSingleExtension<TContainer, TExtension> CreateInstance(FieldDescriptor descriptor) {
+    public static GeneratedSingleExtension<TExtension> CreateInstance(FieldDescriptor descriptor) {
       if (descriptor.IsRepeated) {
         throw new ArgumentException("Must call GeneratedRepeateExtension.CreateInstance() for repeated types.");
       }
-      return new GeneratedSingleExtension<TContainer, TExtension>(descriptor);
+      return new GeneratedSingleExtension<TExtension>(descriptor);
     }
 
     public override object FromReflectionType(object value) {

+ 59 - 56
csharp/ProtocolBuffers/IBuilder.cs

@@ -44,12 +44,18 @@ namespace Google.ProtocolBuffers {
 
     /// <summary>
     /// Allows getting and setting of a field.
-    /// <see cref="IMessage{T}.Item(FieldDescriptor)"/>
+    /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor)"/>
     /// </summary>
     /// <param name="field"></param>
     /// <returns></returns>
     object this[FieldDescriptor field] { get; set; }
 
+    /// <summary>
+    /// Get the message's type's descriptor.
+    /// <see cref="IMessage{TMessage, TBuilder}.DescriptorForType"/>
+    /// </summary>
+    MessageDescriptor DescriptorForType { get; }
+
     /// <summary>
     /// Only present in the nongeneric interface - useful for tests, but
     /// not as much in real life.
@@ -63,13 +69,7 @@ namespace Google.ProtocolBuffers {
     IBuilder SetRepeatedField(FieldDescriptor field, int index, object value);
 
     /// <summary>
-    /// Get the message's type's descriptor.
-    /// <see cref="IMessage{T}.DescriptorForType"/>
-    /// </summary>
-    MessageDescriptor DescriptorForType { get; }
-
-    /// <summary>
-    /// <see cref="IMessage{T}.GetRepeatedFieldCount"/>
+    /// <see cref="IMessage{TMessage, TBuilder}.GetRepeatedFieldCount"/>
     /// </summary>
     /// <param name="field"></param>
     /// <returns></returns>
@@ -77,39 +77,40 @@ namespace Google.ProtocolBuffers {
 
     /// <summary>
     /// Allows getting and setting of a repeated field value.
-    /// <see cref="IMessage{T}.Item(FieldDescriptor, int)"/>
+    /// <see cref="IMessage{TMessage, TBuilder}.Item(FieldDescriptor, int)"/>
     /// </summary>
     object this[FieldDescriptor field, int index] { get; set; }
 
     /// <summary>
-    /// <see cref="IMessage{T}.HasField"/>
+    /// <see cref="IMessage{TMessage, TBuilder}.HasField"/>
     /// </summary>
     bool HasField(FieldDescriptor field);
 
     /// <summary>
-    /// <see cref="IMessage{T}.UnknownFields"/>
+    /// <see cref="IMessage{TMessage, TBuilder}.UnknownFields"/>
     /// </summary>
     UnknownFieldSet UnknownFields { get; set; }
 
-    #region Non-generic versions of generic methods in IBuilder<T>
-    IBuilder Clear();
-    IBuilder MergeFrom(IMessage other);
-    IMessage Build();
-    IMessage BuildPartial();
-    IBuilder Clone();
-    IBuilder MergeFrom(CodedInputStream input);
-    IBuilder MergeFrom(CodedInputStream codedInputStream, ExtensionRegistry extensionRegistry);
-    IMessage DefaultInstanceForType { get; }
+    /// <summary>
+    /// Create a builder for messages of the appropriate type for the given field.
+    /// Messages built with this can then be passed to the various mutation properties
+    /// and methods.
+    /// </summary>
     IBuilder CreateBuilderForField(FieldDescriptor field);
-    IBuilder ClearField(FieldDescriptor field);
-    IBuilder AddRepeatedField(FieldDescriptor field, object value);
-    IBuilder MergeUnknownFields(UnknownFieldSet unknownFields);
-    IBuilder MergeFrom(ByteString data);
-    IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
-    IBuilder MergeFrom(byte[] data);
-    IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
-    IBuilder MergeFrom(Stream input);
-    IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
+
+    #region Methods which are like those of the generic form, but without any knowledge of the type parameters
+    IBuilder WeakAddRepeatedField(FieldDescriptor field, object value);
+    IBuilder WeakClear();
+    IBuilder WeakClearField(FieldDescriptor field);
+    IBuilder WeakMergeFrom(IMessage message);
+    IBuilder WeakMergeFrom(ByteString data);
+    IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry);
+    IBuilder WeakMergeFrom(CodedInputStream input);
+    IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
+    IMessage WeakBuild();
+    IMessage WeakBuildPartial();
+    IBuilder WeakClone();
+    IMessage WeakDefaultInstanceForType { get; }
     #endregion
   }
 
@@ -117,12 +118,15 @@ namespace Google.ProtocolBuffers {
   /// Interface implemented by Protocol Message builders.
   /// TODO(jonskeet): Consider "SetXXX" methods returning the builder, as well as the properties.
   /// </summary>
-  /// <typeparam name="T">Type of message</typeparam>
-  public interface IBuilder<T> : IBuilder where T : IMessage<T> {
+  /// <typeparam name="TMessage">Type of message</typeparam>
+  /// <typeparam name="TBuilder">Type of builder</typeparam>
+  public interface IBuilder<TMessage, TBuilder> : IBuilder
+      where TMessage : IMessage<TMessage, TBuilder> 
+      where TBuilder : IBuilder<TMessage, TBuilder> {
     /// <summary>
     /// Resets all fields to their default values.
     /// </summary>
-    new IBuilder<T> Clear();
+    TBuilder Clear();
 
     /// <summary>
     /// Merge the specified other message into the message being
@@ -137,7 +141,13 @@ namespace Google.ProtocolBuffers {
     /// </summary>
     /// <param name="other"></param>
     /// <returns></returns>
-    IBuilder<T> MergeFrom(T other);
+    TBuilder MergeFrom(TMessage other);
+
+    /// <summary>
+    /// Merge the specified other message which may be a different implementation of
+    /// the same message descriptor.
+    /// </summary>
+    TBuilder MergeFrom(IMessage other);
 
     /// <summary>
     /// Constructs the final message. Once this is called, this Builder instance
@@ -148,19 +158,19 @@ namespace Google.ProtocolBuffers {
     /// <exception cref="UninitializedMessageException">the message
     /// is missing one or more required fields; use BuildPartial to bypass
     /// this check</exception>
-    new T Build();
+    TMessage Build();
 
     /// <summary>
     /// Like Build(), but does not throw an exception if the message is missing
     /// required fields. Instead, a partial message is returned.
     /// </summary>
-    new T BuildPartial();
+    TMessage BuildPartial();
 
     /// <summary>
     /// Clones this builder.
     /// TODO(jonskeet): Explain depth of clone.
     /// </summary>
-    new IBuilder<T> Clone();
+    TBuilder Clone();
 
     /// <summary>
     /// Parses a message of this type from the input and merges it with this
@@ -181,7 +191,7 @@ namespace Google.ProtocolBuffers {
     /// Use BuildPartial to build, which ignores missing required fields.
     /// </list>
     /// </remarks>
-    new IBuilder<T> MergeFrom(CodedInputStream input);
+    TBuilder MergeFrom(CodedInputStream input);
 
     /// <summary>
     /// Like MergeFrom(CodedInputStream), but also parses extensions.
@@ -189,20 +199,13 @@ namespace Google.ProtocolBuffers {
     /// in <paramref name="extensionRegistry"/>. Extensions not in the registry
     /// will be treated as unknown fields.
     /// </summary>
-    new IBuilder<T> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
 
     /// <summary>
     /// Get's the message's type's default instance.
-    /// <see cref="IMessage{T}.DefaultInstanceForType" />
-    /// </summary>
-    new T DefaultInstanceForType { get; }
-
-    /// <summary>
-    /// Create a builder for messages of the appropriate type for the given field.
-    /// Messages built with this can then be passed to the various mutation properties
-    /// and methods.
+    /// <see cref="IMessage{TMessage}.DefaultInstanceForType" />
     /// </summary>
-    //new IBuilder<TField> NewBuilderForField<TField>(FieldDescriptor field) where TField : IMessage<TField>;
+    TMessage DefaultInstanceForType { get; }
 
     /// <summary>
     /// Clears the field. This is exactly equivalent to calling the generated
@@ -210,7 +213,7 @@ namespace Google.ProtocolBuffers {
     /// </summary>
     /// <param name="field"></param>
     /// <returns></returns>
-    new IBuilder<T> ClearField(FieldDescriptor field);
+    TBuilder ClearField(FieldDescriptor field);
 
     /// <summary>
     /// Appends the given value as a new element for the specified repeated field.
@@ -219,12 +222,12 @@ namespace Google.ProtocolBuffers {
     /// the field does not belong to this builder's type, or the value is
     /// of the incorrect type
     /// </exception>
-    new IBuilder<T> AddRepeatedField(FieldDescriptor field, object value);
+    TBuilder AddRepeatedField(FieldDescriptor field, object value);
 
     /// <summary>
     /// Merge some unknown fields into the set for this message.
     /// </summary>
-    new IBuilder<T> MergeUnknownFields(UnknownFieldSet unknownFields);
+    TBuilder MergeUnknownFields(UnknownFieldSet unknownFields);
 
     #region Convenience methods
     // TODO(jonskeet): Implement these as extension methods?
@@ -233,28 +236,28 @@ namespace Google.ProtocolBuffers {
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream).
     /// </summary>
-    new IBuilder<T> MergeFrom(ByteString data);
+    TBuilder MergeFrom(ByteString data);
 
     /// <summary>
     /// Parse <paramref name="data"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream, ExtensionRegistry).
     /// </summary>
-    new IBuilder<T> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
 
     /// <summary>
     /// Parse <paramref name="data"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream).
     /// </summary>
-    new IBuilder<T> MergeFrom(byte[] data);
+    TBuilder MergeFrom(byte[] data);
 
     /// <summary>
     /// Parse <paramref name="data"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream, ExtensionRegistry).
     /// </summary>
-    new IBuilder<T> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
 
     /// <summary>
     /// Parse <paramref name="input"/> as a message of this type and merge
@@ -265,14 +268,14 @@ namespace Google.ProtocolBuffers {
     /// stream which limits reading. Despite usually reading the entire
     /// stream, this method never closes the stream.
     /// </summary>
-    new IBuilder<T> MergeFrom(Stream input);
+    TBuilder MergeFrom(Stream input);
 
     /// <summary>
     /// Parse <paramref name="input"/> as a message of this type and merge
     /// it with the message being built. This is just a small wrapper around
     /// MergeFrom(CodedInputStream, ExtensionRegistry).
     /// </summary>
-    new IBuilder<T> MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
+    TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
     #endregion
   }
 }

+ 17 - 23
csharp/ProtocolBuffers/IMessage.cs

@@ -21,11 +21,8 @@ using Google.ProtocolBuffers.Descriptors;
 namespace Google.ProtocolBuffers {
 
   /// <summary>
-  /// Non-generic interface implemented by all Protocol Buffers messages.
-  /// Some members are repeated in the generic interface but with a
-  /// type-specific signature. Type-safe implementations
-  /// are encouraged to implement these non-generic members explicitly,
-  /// and the generic members implicitly.
+  /// Non-generic interface used for all parts of the API which don't require
+  /// any type knowledge.
   /// </summary>
   public interface IMessage {
     /// <summary>
@@ -152,27 +149,17 @@ namespace Google.ProtocolBuffers {
     void WriteTo(Stream output);
     #endregion
 
-    #region Weakly typed members
     /// <summary>
-    /// Returns an instance of this message type with all fields set to
-    /// their default values. This may or may not be a singleton. This differs
-    /// from the DefaultInstance property of each generated message class in that this
-    /// method is an abstract method of IMessage whereas DefaultInstance is
-    /// a static property of a specific class. They return the same thing.
+    /// Creates a builder for the type, but in a weakly typed manner. This
+    /// is typically implemented by strongly typed builders by just returning
+    /// the result of CreateBuilderForType.
     /// </summary>
-    IMessage DefaultInstanceForType { get; }
+    IBuilder WeakCreateBuilderForType();
 
-    /// <summary>
-    /// Constructs a new builder for a message of the same type as this message.
-    /// </summary>
-    IBuilder CreateBuilderForType();
-    #endregion
+    IMessage WeakDefaultInstanceForType { get; }
   }
 
-  /// <summary>
-  /// Type-safe interface for all generated messages to implement.
-  /// </summary>
-  public interface IMessage<T> : IMessage where T : IMessage<T> {
+  public interface IMessage<TMessage> : IMessage {
     /// <summary>
     /// Returns an instance of this message type with all fields set to
     /// their default values. This may or may not be a singleton. This differs
@@ -180,13 +167,20 @@ namespace Google.ProtocolBuffers {
     /// method is an abstract method of IMessage whereas DefaultInstance is
     /// a static property of a specific class. They return the same thing.
     /// </summary>
-    new T DefaultInstanceForType { get; }
+    TMessage DefaultInstanceForType { get; }
+  }
 
+  /// <summary>
+  /// Type-safe interface for all generated messages to implement.
+  /// </summary>
+  public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>
+      where TMessage : IMessage<TMessage, TBuilder> 
+      where TBuilder : IBuilder<TMessage, TBuilder> {
     #region Builders
     /// <summary>
     /// Constructs a new builder for a message of the same type as this message.
     /// </summary>
-    new IBuilder<T> CreateBuilderForType();
+    TBuilder CreateBuilderForType();
     #endregion
   }
 }

+ 2 - 2
csharp/ProtocolBuffers/InvalidProtocolBufferException.cs

@@ -67,13 +67,13 @@ namespace Google.ProtocolBuffers {
     internal static InvalidProtocolBufferException RecursionLimitExceeded() {
       return new InvalidProtocolBufferException(
         "Protocol message had too many levels of nesting.  May be malicious.  " +
-        "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
+        "Use CodedInputStream.SetRecursionLimit() to increase the depth limit.");
     }
 
     internal static InvalidProtocolBufferException SizeLimitExceeded() {
       return new InvalidProtocolBufferException(
         "Protocol message was too large.  May be malicious.  " +
-        "Use CodedInputStream.setSizeLimit() to increase the size limit.");
+        "Use CodedInputStream.SetSizeLimit() to increase the size limit.");
     }
   }
 }

+ 5 - 4
csharp/ProtocolBuffers/RpcUtil.cs

@@ -21,12 +21,13 @@ namespace Google.ProtocolBuffers {
     /// callback is given a message with a different descriptor, an
     /// exception will be thrown.
     /// </summary>
-    public static Action<IMessage> GeneralizeCallback<T>(Action<T> action, T defaultInstance)
-        where T : class, IMessage<T> {
+    public static Action<IMessage> GeneralizeCallback<TMessage, TBuilder>(Action<TMessage> action, TMessage defaultInstance)
+        where TMessage : class, IMessage<TMessage, TBuilder> 
+        where TBuilder : IBuilder<TMessage, TBuilder> {
       return message => {
-        T castMessage = message as T;
+        TMessage castMessage = message as TMessage;
         if (castMessage == null) {
-          castMessage = (T) defaultInstance.CreateBuilderForType().MergeFrom(message).Build();
+          castMessage = defaultInstance.CreateBuilderForType().MergeFrom(message).Build();
         }
         action(castMessage);
       };

+ 1 - 0
csharp/ProtocolBuffers/TextFormat.cs

@@ -44,6 +44,7 @@ namespace Google.ProtocolBuffers {
     }
 
     private static void Print(IMessage message, TextGenerator generator) {
+      // TODO(jonskeet): Check why descriptor is never used.
       MessageDescriptor descriptor = message.DescriptorForType;
       foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields) {
         PrintField(entry.Key, entry.Value, generator);

+ 4 - 4
src/google/protobuf/compiler/csharp/csharp_extension.cc

@@ -57,12 +57,12 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
   if (descriptor_->is_repeated()) {
     printer->Print(vars,
       "public static readonly\r\n"
-      "  pb::GeneratedExtensionBase<$containing_type$, scg::IList<$type$>> $name$ =\r\n"
-      "      pb::GeneratedRepeatExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
+      "  pb::GeneratedExtensionBase<scg::IList<$type$>> $name$ =\r\n"
+      "      pb::GeneratedRepeatExtension<$type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
   } else {
     printer->Print(vars,
-      "public static readonly pb::GeneratedExtensionBase<$containing_type$, $type$> $name$ =\r\n"
-      "      pb::GeneratedSingleExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
+      "public static readonly pb::GeneratedExtensionBase<$type$> $name$ =\r\n"
+      "      pb::GeneratedSingleExtension<$type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
   }
 }
 

+ 16 - 10
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -423,7 +423,7 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
 void MessageGenerator::GenerateBuilder(io::Printer* printer) {
   printer->Print(
     "public static Builder CreateBuilder() { return new Builder(); }\r\n"
-    "public override IBuilder<$classname$> CreateBuilderForType() { return new Builder(); }\r\n"
+    "public override Builder CreateBuilderForType() { return new Builder(); }\r\n"
     "public static Builder CreateBuilder($classname$ prototype) {\r\n"
     "  return (Builder) new Builder().MergeFrom(prototype);\r\n"
     "}\r\n"
@@ -441,8 +441,14 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
       "classname", ClassName(descriptor_),
       "access", ClassAccessLevel(descriptor_->file()));
   }
+
   printer->Indent();
 
+  printer->Print(
+      "protected override Builder ThisBuilder {\r\n"
+      "  get { return this; }\r\n"
+      "}\r\n\r\n");
+
   GenerateCommonBuilderMethods(printer);
 
   if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
@@ -475,12 +481,12 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
     "  get { return result; }\r\n"
     "}\r\n"
     "\r\n"
-    "public override IBuilder<$classname$> Clear() {\r\n"
+    "public override Builder Clear() {\r\n"
     "  result = new $classname$();\r\n"
     "  return this;\r\n"
     "}\r\n"
     "\r\n"
-    "public override IBuilder<$classname$> Clone() {\r\n"
+    "public override Builder Clone() {\r\n"
     "  return new Builder().MergeFrom(result);\r\n"
     "}\r\n"
     "\r\n"
@@ -516,14 +522,14 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
 
   // -----------------------------------------------------------------
 
-  //TODO(jonskeet): Work out what this is really for...
   if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
     printer->Print(
-      "protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {\r\n"
+      /*
+      "protected override Builder MergeFrom(CodedInputStream data, ExtensionRegistry extensionRegistry) {\r\n"
       "  return MergeFrom(data, extensionRegistry);\r\n"
       "}\r\n"
-      "\r\n"
-      "public override IBuilder MergeFrom(pb::IMessage other) {\r\n"
+      "\r\n"*/
+      "public override Builder MergeFrom(pb::IMessage other) {\r\n"
       "  if (other is $classname$) {\r\n"
       "    return MergeFrom(($classname$) other);\r\n"
       "  } else {\r\n"
@@ -532,7 +538,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
       "  }\r\n"
       "}\r\n"
       "\r\n"
-      "public override IBuilder<$classname$> MergeFrom($classname$ other) {\r\n"
+      "public override Builder MergeFrom($classname$ other) {\r\n"
       // Optimization:  If other is the default instance, we know none of its
       //   fields are set so we can skip the merge.
       "  if (other == $classname$.DefaultInstance) return this;\r\n",
@@ -559,11 +565,11 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
     SortFieldsByNumber(descriptor_));
 
   printer->Print(
-    "public override IBuilder<$classname$> MergeFrom(pb::CodedInputStream input) {\r\n"
+    "public override Builder MergeFrom(pb::CodedInputStream input) {\r\n"
     "  return MergeFrom(input, pb::ExtensionRegistry.Empty);\r\n"
     "}\r\n"
     "\r\n"
-    "public override IBuilder<$classname$> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\r\n",
+    "public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\r\n",
     "classname", ClassName(descriptor_));
   printer->Indent();
 

+ 1 - 1
src/google/protobuf/compiler/csharp/csharp_service.cc

@@ -199,7 +199,7 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
       "    controller,\r\n"
       "    request,\r\n"
       "    $output$.DefaultInstance,\r\n"
-      "    pb::RpcUtil.GeneralizeCallback(done, $output$.DefaultInstance));\r\n"
+      "    pb::RpcUtil.GeneralizeCallback<$output$, $output$.Builder>(done, $output$.DefaultInstance));\r\n"
       "}\r\n");
   }
 

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác