Browse Source

The great generics revisiting.

Jon Skeet 17 years ago
parent
commit
f26f8dce02
36 changed files with 960 additions and 1008 deletions
  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);
       }
       

File diff suppressed because it is too large
+ 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);

File diff suppressed because it is too large
+ 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");
   }
 

Some files were not shown because too many files changed in this diff