Browse Source

Implemented popsicle immutability for lists. Modified MessageStreamIterator to be singly generic.

Jon Skeet 17 years ago
parent
commit
0bf2ad145d

+ 64 - 0
csharp/ProtocolBuffers.Test/Collections/PopsicleListTest.cs

@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+
+namespace Google.ProtocolBuffers.Collections {
+  [TestFixture]
+  public class PopsicleListTest {
+
+    [Test]
+    public void MutatingOperationsOnFrozenList() {
+      PopsicleList<string> list = new PopsicleList<string>();
+      list.MakeReadOnly();
+      AssertNotSupported(() => list.Add(""));
+      AssertNotSupported(() => list.Clear());
+      AssertNotSupported(() => list.Insert(0, ""));
+      AssertNotSupported(() => list.Remove(""));
+      AssertNotSupported(() => list.RemoveAt(0));
+    }
+
+    [Test]
+    public void NonMutatingOperationsOnFrozenList() {
+      PopsicleList<string> list = new PopsicleList<string>();
+      list.MakeReadOnly();
+      Assert.IsFalse(list.Contains(""));
+      Assert.AreEqual(0, list.Count);
+      list.CopyTo(new string[5], 0);
+      list.GetEnumerator();
+      Assert.AreEqual(-1, list.IndexOf(""));
+      Assert.IsTrue(list.IsReadOnly);
+    }
+
+    [Test]
+    public void MutatingOperationsOnFluidList() {
+      PopsicleList<string> list = new PopsicleList<string>();
+      list.Add("");
+      list.Clear();
+      list.Insert(0, "");
+      list.Remove("");
+      list.Add("x"); // Just to make the next call valid
+      list.RemoveAt(0);
+    }
+
+    [Test]
+    public void NonMutatingOperationsOnFluidList() {
+      PopsicleList<string> list = new PopsicleList<string>();
+      Assert.IsFalse(list.Contains(""));
+      Assert.AreEqual(0, list.Count);
+      list.CopyTo(new string[5], 0);
+      list.GetEnumerator();
+      Assert.AreEqual(-1, list.IndexOf(""));
+      Assert.IsFalse(list.IsReadOnly);
+    }
+
+    private static void AssertNotSupported(Action action) {
+      try {
+        action();
+        Assert.Fail("Expected NotSupportedException");
+      } catch (NotSupportedException) {
+        // Expected
+      }
+    }
+  }
+}

+ 46 - 1
csharp/ProtocolBuffers.Test/GeneratedMessageTest.cs

@@ -13,6 +13,8 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+using System;
+using System.Collections.Generic;
 using Google.ProtocolBuffers.Descriptors;
 using Google.ProtocolBuffers.TestProtos;
 using NUnit.Framework;
@@ -28,7 +30,50 @@ namespace Google.ProtocolBuffers {
       reflectionTester = ReflectionTester.CreateTestAllTypesInstance();
       extensionsReflectionTester = ReflectionTester.CreateTestAllExtensionsInstance();
     }
-    
+
+    [Test]
+    public void RepeatedAddPrimitiveBeforeBuild() {
+      TestAllTypes message = new TestAllTypes.Builder { RepeatedInt32List = { 1, 2, 3 } }.Build();
+      TestUtil.AssertEqual(new int[]{1, 2, 3}, message.RepeatedInt32List);
+    }
+
+    [Test]
+    public void AddPrimitiveFailsAfterBuild() {
+      TestAllTypes.Builder builder = new TestAllTypes.Builder();
+      IList<int> list = builder.RepeatedInt32List;
+      list.Add(1); // Fine
+      builder.Build();
+
+      try {
+        list.Add(2);
+        Assert.Fail("List should be frozen");
+      } catch (NotSupportedException) {
+        // Expected
+      }
+    }
+
+    [Test]
+    public void RepeatedAddMessageBeforeBuild() {
+      TestAllTypes message = new TestAllTypes.Builder {
+          RepeatedNestedMessageList = { new TestAllTypes.Types.NestedMessage.Builder { Bb = 10 }.Build() } }.Build();
+      Assert.AreEqual(1, message.RepeatedNestedMessageCount);
+      Assert.AreEqual(10, message.RepeatedNestedMessageList[0].Bb);
+    }
+
+    [Test]
+    public void AddMessageFailsAfterBuild() {
+      TestAllTypes.Builder builder = new TestAllTypes.Builder();
+      IList<TestAllTypes.Types.NestedMessage> list = builder.RepeatedNestedMessageList;
+      builder.Build();
+
+      try {
+        list.Add(new TestAllTypes.Types.NestedMessage.Builder { Bb = 10 }.Build());
+        Assert.Fail("List should be frozen");
+      } catch (NotSupportedException) {
+        // Expected
+      }
+    }
+
     [Test]
     public void DefaultInstance() {
       Assert.AreSame(TestAllTypes.DefaultInstance, TestAllTypes.DefaultInstance.DefaultInstanceForType);

+ 1 - 1
csharp/ProtocolBuffers.Test/MessageStreamIteratorTest.cs

@@ -11,7 +11,7 @@ namespace Google.ProtocolBuffers {
     [Test]
     public void ThreeMessagesInMemory() {
       MemoryStream stream = new MemoryStream(MessageStreamWriterTest.ThreeMessageData);      
-      IEnumerable<NestedMessage> iterator = MessageStreamIterator.FromStreamProvider<NestedMessage>(() => stream);
+      IEnumerable<NestedMessage> iterator = MessageStreamIterator<NestedMessage>.FromStreamProvider(() => stream);
       List<NestedMessage> messages = new List<NestedMessage>(iterator);
 
       Assert.AreEqual(3, messages.Count);

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

@@ -50,6 +50,7 @@
     <Compile Include="ByteStringTest.cs" />
     <Compile Include="CodedInputStreamTest.cs" />
     <Compile Include="CodedOutputStreamTest.cs" />
+    <Compile Include="Collections\PopsicleListTest.cs" />
     <Compile Include="DescriptorsTest.cs" />
     <Compile Include="DynamicMessageTest.cs" />
     <Compile Include="GeneratedMessageTest.cs" />

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

@@ -7,7 +7,7 @@ using scg = global::System.Collections.Generic;
 namespace Google.ProtocolBuffers.TestProtos {
   
   public sealed partial class MessageWithNoOuter : pb::GeneratedMessage<MessageWithNoOuter, MessageWithNoOuter.Builder> {
-    private static readonly MessageWithNoOuter defaultInstance = new MessageWithNoOuter();
+    private static readonly MessageWithNoOuter defaultInstance = new Builder().BuildPartial();
     public static MessageWithNoOuter DefaultInstance {
       get { return defaultInstance; }
     }
@@ -35,7 +35,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public sealed partial class NestedMessage : pb::GeneratedMessage<NestedMessage, NestedMessage.Builder> {
-        private static readonly NestedMessage defaultInstance = new NestedMessage();
+        private static readonly NestedMessage defaultInstance = new Builder().BuildPartial();
         public static NestedMessage DefaultInstance {
           get { return defaultInstance; }
         }
@@ -179,7 +179,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     // repeated .protobuf_unittest.TestAllTypes foreign = 2;
-    private scg::IList<global::Google.ProtocolBuffers.TestProtos.TestAllTypes> foreign_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestAllTypes> foreign_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>();
     public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestAllTypes> ForeignList {
       get { return foreign_; } 
     }
@@ -278,9 +278,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override global::Google.ProtocolBuffers.TestProtos.MessageWithNoOuter BuildPartial() {
-        if (result.foreign_ != pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>.Empty) {
-          result.foreign_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>.AsReadOnly(result.foreign_);
-        }
+        result.foreign_.MakeReadOnly();
         global::Google.ProtocolBuffers.TestProtos.MessageWithNoOuter returnMe = result;
         result = null;
         return returnMe;
@@ -324,7 +322,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       // repeated .protobuf_unittest.TestAllTypes foreign = 2;
       public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestAllTypes> ForeignList {
-        get { return pbc::Lists.AsReadOnly(result.foreign_); }
+        get { return result.foreign_; }
       }
       public int ForeignCount {
         get { return result.ForeignCount; }
@@ -341,28 +339,19 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder AddForeign(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) {
-        if (result.foreign_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>.Empty) {
-          result.foreign_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>();
-        }
         result.foreign_.Add(value);
         return this;
       }
       public Builder AddForeign(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder builderForValue) {
-        if (result.foreign_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>.Empty) {
-          result.foreign_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>();
-        }
         result.foreign_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeForeign(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestAllTypes> values) {
-        if (result.foreign_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>.Empty) {
-          result.foreign_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>();
-        }
         base.AddRange(values, result.foreign_);
         return this;
       }
       public Builder ClearForeign() {
-        result.foreign_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestAllTypes>.Empty;
+        result.foreign_.Clear();
         return this;
       }
       

+ 5 - 19
csharp/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs

@@ -55,7 +55,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   
   #region Messages
   public sealed partial class TestEmbedOptimizedForSize : pb::GeneratedMessage<TestEmbedOptimizedForSize, TestEmbedOptimizedForSize.Builder> {
-    private static readonly TestEmbedOptimizedForSize defaultInstance = new TestEmbedOptimizedForSize();
+    private static readonly TestEmbedOptimizedForSize defaultInstance = new Builder().BuildPartial();
     public static TestEmbedOptimizedForSize DefaultInstance {
       get { return defaultInstance; }
     }
@@ -87,7 +87,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
     
     // repeated .protobuf_unittest.TestOptimizedForSize repeated_message = 2;
-    private scg::IList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> repeatedMessage_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> repeatedMessage_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>();
     public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> RepeatedMessageList {
       get { return repeatedMessage_; } 
     }
@@ -211,9 +211,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize BuildPartial() {
-        if (result.repeatedMessage_ != pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>.Empty) {
-          result.repeatedMessage_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>.AsReadOnly(result.repeatedMessage_);
-        }
+        result.repeatedMessage_.MakeReadOnly();
         global::Google.ProtocolBuffers.TestProtos.TestEmbedOptimizedForSize returnMe = result;
         result = null;
         return returnMe;
@@ -234,9 +232,6 @@ namespace Google.ProtocolBuffers.TestProtos {
           MergeOptionalMessage(other.OptionalMessage);
         }
         if (other.repeatedMessage_.Count != 0) {
-          if (result.repeatedMessage_.Count == 0) {
-            result.repeatedMessage_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>();
-          }
           base.AddRange(other.repeatedMessage_, result.repeatedMessage_);
         }
         this.MergeUnknownFields(other.UnknownFields);
@@ -321,7 +316,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       // repeated .protobuf_unittest.TestOptimizedForSize repeated_message = 2;
       public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> RepeatedMessageList {
-        get { return pbc::Lists.AsReadOnly(result.repeatedMessage_); }
+        get { return result.repeatedMessage_; }
       }
       public int RepeatedMessageCount {
         get { return result.RepeatedMessageCount; }
@@ -338,28 +333,19 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize value) {
-        if (result.repeatedMessage_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>.Empty) {
-          result.repeatedMessage_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>();
-        }
         result.repeatedMessage_.Add(value);
         return this;
       }
       public Builder AddRepeatedMessage(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder builderForValue) {
-        if (result.repeatedMessage_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>.Empty) {
-          result.repeatedMessage_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>();
-        }
         result.repeatedMessage_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeRepeatedMessage(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize> values) {
-        if (result.repeatedMessage_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>.Empty) {
-          result.repeatedMessage_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>();
-        }
         base.AddRange(values, result.repeatedMessage_);
         return this;
       }
       public Builder ClearRepeatedMessage() {
-        result.repeatedMessage_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize>.Empty;
+        result.repeatedMessage_.Clear();
         return this;
       }
     }

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

@@ -55,7 +55,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   
   #region Messages
   public sealed partial class ImportMessage : pb::GeneratedMessage<ImportMessage, ImportMessage.Builder> {
-    private static readonly ImportMessage defaultInstance = new ImportMessage();
+    private static readonly ImportMessage defaultInstance = new Builder().BuildPartial();
     public static ImportMessage DefaultInstance {
       get { return defaultInstance; }
     }

+ 10 - 24
csharp/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs

@@ -95,7 +95,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   
   #region Messages
   public sealed partial class TestMessageSet : pb::ExtendableMessage<TestMessageSet, TestMessageSet.Builder> {
-    private static readonly TestMessageSet defaultInstance = new TestMessageSet();
+    private static readonly TestMessageSet defaultInstance = new Builder().BuildPartial();
     public static TestMessageSet DefaultInstance {
       get { return defaultInstance; }
     }
@@ -264,7 +264,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   }
   
   public sealed partial class TestMessageSetContainer : pb::GeneratedMessage<TestMessageSetContainer, TestMessageSetContainer.Builder> {
-    private static readonly TestMessageSetContainer defaultInstance = new TestMessageSetContainer();
+    private static readonly TestMessageSetContainer defaultInstance = new Builder().BuildPartial();
     public static TestMessageSetContainer DefaultInstance {
       get { return defaultInstance; }
     }
@@ -495,7 +495,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   }
   
   public sealed partial class TestMessageSetExtension1 : pb::GeneratedMessage<TestMessageSetExtension1, TestMessageSetExtension1.Builder> {
-    private static readonly TestMessageSetExtension1 defaultInstance = new TestMessageSetExtension1();
+    private static readonly TestMessageSetExtension1 defaultInstance = new Builder().BuildPartial();
     public static TestMessageSetExtension1 DefaultInstance {
       get { return defaultInstance; }
     }
@@ -709,7 +709,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   }
   
   public sealed partial class TestMessageSetExtension2 : pb::GeneratedMessage<TestMessageSetExtension2, TestMessageSetExtension2.Builder> {
-    private static readonly TestMessageSetExtension2 defaultInstance = new TestMessageSetExtension2();
+    private static readonly TestMessageSetExtension2 defaultInstance = new Builder().BuildPartial();
     public static TestMessageSetExtension2 DefaultInstance {
       get { return defaultInstance; }
     }
@@ -923,7 +923,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   }
   
   public sealed partial class RawMessageSet : pb::GeneratedMessage<RawMessageSet, RawMessageSet.Builder> {
-    private static readonly RawMessageSet defaultInstance = new RawMessageSet();
+    private static readonly RawMessageSet defaultInstance = new Builder().BuildPartial();
     public static RawMessageSet DefaultInstance {
       get { return defaultInstance; }
     }
@@ -947,7 +947,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     #region Nested types
     public static class Types {
       public sealed partial class Item : pb::GeneratedMessage<Item, Item.Builder> {
-        private static readonly Item defaultInstance = new Item();
+        private static readonly Item defaultInstance = new Builder().BuildPartial();
         public static Item DefaultInstance {
           get { return defaultInstance; }
         }
@@ -1201,7 +1201,7 @@ namespace Google.ProtocolBuffers.TestProtos {
     #endregion
     
     // repeated group Item = 1 {
-    private scg::IList<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> item_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> item_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>();
     public scg::IList<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> ItemList {
       get { return item_; } 
     }
@@ -1316,9 +1316,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       }
       
       public override global::Google.ProtocolBuffers.TestProtos.RawMessageSet BuildPartial() {
-        if (result.item_ != pbc::Lists<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>.Empty) {
-          result.item_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>.AsReadOnly(result.item_);
-        }
+        result.item_.MakeReadOnly();
         global::Google.ProtocolBuffers.TestProtos.RawMessageSet returnMe = result;
         result = null;
         return returnMe;
@@ -1336,9 +1334,6 @@ namespace Google.ProtocolBuffers.TestProtos {
       public override Builder MergeFrom(global::Google.ProtocolBuffers.TestProtos.RawMessageSet other) {
         if (other == global::Google.ProtocolBuffers.TestProtos.RawMessageSet.DefaultInstance) return this;
         if (other.item_.Count != 0) {
-          if (result.item_.Count == 0) {
-            result.item_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>();
-          }
           base.AddRange(other.item_, result.item_);
         }
         this.MergeUnknownFields(other.UnknownFields);
@@ -1379,7 +1374,7 @@ namespace Google.ProtocolBuffers.TestProtos {
       
       // repeated group Item = 1 {
       public scg::IList<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> ItemList {
-        get { return pbc::Lists.AsReadOnly(result.item_); }
+        get { return result.item_; }
       }
       public int ItemCount {
         get { return result.ItemCount; }
@@ -1396,28 +1391,19 @@ namespace Google.ProtocolBuffers.TestProtos {
         return this;
       }
       public Builder AddItem(global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item value) {
-        if (result.item_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>.Empty) {
-          result.item_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>();
-        }
         result.item_.Add(value);
         return this;
       }
       public Builder AddItem(global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.Builder builderForValue) {
-        if (result.item_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>.Empty) {
-          result.item_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>();
-        }
         result.item_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeItem(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item> values) {
-        if (result.item_ == pbc::Lists<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>.Empty) {
-          result.item_ = new scg::List<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>();
-        }
         base.AddRange(values, result.item_);
         return this;
       }
       public Builder ClearItem() {
-        result.item_ = pbc::Lists<global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item>.Empty;
+        result.item_.Clear();
         return this;
       }
     }

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

@@ -54,7 +54,7 @@ namespace Google.ProtocolBuffers.TestProtos {
   
   #region Messages
   public sealed partial class TestOptimizedForSize : pb::ExtendableMessage<TestOptimizedForSize, TestOptimizedForSize.Builder> {
-    private static readonly TestOptimizedForSize defaultInstance = new TestOptimizedForSize();
+    private static readonly TestOptimizedForSize defaultInstance = new Builder().BuildPartial();
     public static TestOptimizedForSize DefaultInstance {
       get { return defaultInstance; }
     }

File diff suppressed because it is too large
+ 98 - 277
csharp/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs


+ 95 - 0
csharp/ProtocolBuffers/Collections/PopsicleList.cs

@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections;
+
+namespace Google.ProtocolBuffers.Collections {
+  /// <summary>
+  /// Proxies calls to a <see cref="List{T}" />, but allows the list
+  /// to be made read-only (with the <see cref="MakeReadOnly" /> method), 
+  /// after which any modifying methods throw <see cref="NotSupportedException" />.
+  /// </summary>
+  public sealed class PopsicleList<T> : IList<T> {
+
+    private readonly List<T> items = new List<T>();
+    private bool readOnly = false;
+
+    /// <summary>
+    /// Makes this list read-only ("freezes the popsicle"). From this
+    /// point on, mutating methods (Clear, Add etc) will throw a
+    /// NotSupportedException. There is no way of "defrosting" the list afterwards.
+    /// </summary>
+    public void MakeReadOnly() {
+      readOnly = true;
+    }
+
+    public int IndexOf(T item) {
+      return items.IndexOf(item);
+    }
+
+    public void Insert(int index, T item) {
+      ValidateModification();
+      items.Insert(index, item);
+    }
+
+    public void RemoveAt(int index) {
+      ValidateModification();
+      items.RemoveAt(index);
+    }
+
+    public T this[int index] {
+      get {
+        return items[index];
+      }
+      set {
+        ValidateModification();
+        items[index] = value;
+      }
+    }
+
+    public void Add(T item) {
+      ValidateModification();
+      items.Add(item);
+    }
+
+    public void Clear() {
+      ValidateModification();
+      items.Clear();
+    }
+
+    public bool Contains(T item) {
+      return items.Contains(item);
+    }
+
+    public void CopyTo(T[] array, int arrayIndex) {
+      items.CopyTo(array, arrayIndex);
+    }
+
+    public int Count {
+      get { return items.Count; }
+    }
+
+    public bool IsReadOnly {
+      get { return readOnly; }
+    }
+
+    public bool Remove(T item) {
+      ValidateModification();
+      return items.Remove(item);
+    }
+
+    public IEnumerator<T> GetEnumerator() {
+      return items.GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator() {
+      return GetEnumerator();
+    }
+
+    private void ValidateModification() {
+      if (readOnly) {
+        throw new NotSupportedException("List is read-only");
+      }
+    }
+  }
+}

+ 26 - 2
csharp/ProtocolBuffers/Delegates.cs

@@ -1,8 +1,32 @@
-using System.IO;
-namespace Google.ProtocolBuffers {
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.
+// http://code.google.com/p/protobuf/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+using System.IO;
 
+namespace Google.ProtocolBuffers {
   /// <summary>
   /// Delegate to return a stream when asked, used by MessageStreamIterator.
   /// </summary>
   public delegate Stream StreamProvider();
+
+  // These delegate declarations mirror the ones in .NET 3.5 for the sake of familiarity.
+  internal delegate TResult Func<TResult>();
+  internal delegate TResult Func<T, TResult>(T arg);
+  internal delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
+  internal delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
+  internal delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+  internal delegate void Action();
+  internal delegate void Action<T1, T2>(T1 arg1, T2 arg2);
 }

+ 69 - 246
csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs

@@ -255,7 +255,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   
   #region Messages
   public sealed partial class FileDescriptorSet : pb::GeneratedMessage<FileDescriptorSet, FileDescriptorSet.Builder> {
-    private static readonly FileDescriptorSet defaultInstance = new FileDescriptorSet();
+    private static readonly FileDescriptorSet defaultInstance = new Builder().BuildPartial();
     public static FileDescriptorSet DefaultInstance {
       get { return defaultInstance; }
     }
@@ -277,7 +277,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.FileDescriptorProto file = 1;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> file_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> file_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> FileList {
       get { return file_; } 
     }
@@ -389,9 +389,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet BuildPartial() {
-        if (result.file_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>.Empty) {
-          result.file_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>.AsReadOnly(result.file_);
-        }
+        result.file_.MakeReadOnly();
         global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet returnMe = result;
         result = null;
         return returnMe;
@@ -409,9 +407,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       public override Builder MergeFrom(global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet other) {
         if (other == global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorSet.DefaultInstance) return this;
         if (other.file_.Count != 0) {
-          if (result.file_.Count == 0) {
-            result.file_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>();
-          }
           base.AddRange(other.file_, result.file_);
         }
         this.MergeUnknownFields(other.UnknownFields);
@@ -452,7 +447,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       // repeated .google.protobuf.FileDescriptorProto file = 1;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> FileList {
-        get { return pbc::Lists.AsReadOnly(result.file_); }
+        get { return result.file_; }
       }
       public int FileCount {
         get { return result.FileCount; }
@@ -469,35 +464,26 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddFile(global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto value) {
-        if (result.file_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>.Empty) {
-          result.file_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>();
-        }
         result.file_.Add(value);
         return this;
       }
       public Builder AddFile(global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.Builder builderForValue) {
-        if (result.file_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>.Empty) {
-          result.file_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>();
-        }
         result.file_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeFile(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto> values) {
-        if (result.file_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>.Empty) {
-          result.file_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>();
-        }
         base.AddRange(values, result.file_);
         return this;
       }
       public Builder ClearFile() {
-        result.file_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto>.Empty;
+        result.file_.Clear();
         return this;
       }
     }
   }
   
   public sealed partial class FileDescriptorProto : pb::GeneratedMessage<FileDescriptorProto, FileDescriptorProto.Builder> {
-    private static readonly FileDescriptorProto defaultInstance = new FileDescriptorProto();
+    private static readonly FileDescriptorProto defaultInstance = new Builder().BuildPartial();
     public static FileDescriptorProto DefaultInstance {
       get { return defaultInstance; }
     }
@@ -539,9 +525,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated string dependency = 3;
-    private scg::IList<string> dependency_ = pbc::Lists<string>.Empty;
+    private pbc::PopsicleList<string> dependency_ = new pbc::PopsicleList<string>();
     public scg::IList<string> DependencyList {
-      get { return dependency_; }
+      get { return dependency_; } 
     }
     public int DependencyCount {
       get { return dependency_.Count; }
@@ -551,7 +537,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.DescriptorProto message_type = 4;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> messageType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> messageType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> MessageTypeList {
       get { return messageType_; } 
     }
@@ -563,7 +549,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> enumType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList {
       get { return enumType_; } 
     }
@@ -575,7 +561,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.ServiceDescriptorProto service = 6;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> service_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> service_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> ServiceList {
       get { return service_; } 
     }
@@ -587,7 +573,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.FieldDescriptorProto extension = 7;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> extension_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList {
       get { return extension_; } 
     }
@@ -752,19 +738,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto BuildPartial() {
-        result.dependency_ = pbc::Lists<string>.AsReadOnly(result.dependency_);
-        if (result.messageType_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.messageType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.AsReadOnly(result.messageType_);
-        }
-        if (result.enumType_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.AsReadOnly(result.enumType_);
-        }
-        if (result.service_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>.Empty) {
-          result.service_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>.AsReadOnly(result.service_);
-        }
-        if (result.extension_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.AsReadOnly(result.extension_);
-        }
+        result.dependency_.MakeReadOnly();
+        result.messageType_.MakeReadOnly();
+        result.enumType_.MakeReadOnly();
+        result.service_.MakeReadOnly();
+        result.extension_.MakeReadOnly();
         global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto returnMe = result;
         result = null;
         return returnMe;
@@ -788,33 +766,18 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
           Package = other.Package;
         }
         if (other.dependency_.Count != 0) {
-          if (result.dependency_.Count == 0) {
-            result.dependency_ = new scg::List<string>();
-          }
           base.AddRange(other.dependency_, result.dependency_);
         }
         if (other.messageType_.Count != 0) {
-          if (result.messageType_.Count == 0) {
-            result.messageType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-          }
           base.AddRange(other.messageType_, result.messageType_);
         }
         if (other.enumType_.Count != 0) {
-          if (result.enumType_.Count == 0) {
-            result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-          }
           base.AddRange(other.enumType_, result.enumType_);
         }
         if (other.service_.Count != 0) {
-          if (result.service_.Count == 0) {
-            result.service_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>();
-          }
           base.AddRange(other.service_, result.service_);
         }
         if (other.extension_.Count != 0) {
-          if (result.extension_.Count == 0) {
-            result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-          }
           base.AddRange(other.extension_, result.extension_);
         }
         if (other.HasOptions) {
@@ -935,7 +898,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       // repeated string dependency = 3;
       public scg::IList<string> DependencyList {
-        get { return pbc::Lists<string>.AsReadOnly(result.dependency_); }
+        get { return result.dependency_; }
       }
       public int DependencyCount {
         get { return result.DependencyCount; }
@@ -948,27 +911,21 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddDependency(string value) {
-        if (result.dependency_.Count == 0) {
-          result.dependency_ = new scg::List<string>();
-        }
         result.dependency_.Add(value);
         return this;
       }
       public Builder AddRangeDependency(scg::IEnumerable<string> values) {
-        if (result.dependency_.Count == 0) {
-          result.dependency_ = new scg::List<string>();
-        }
         base.AddRange(values, result.dependency_);
         return this;
       }
       public Builder ClearDependency() {
-        result.dependency_ = pbc::Lists<string>.Empty;
+        result.dependency_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.DescriptorProto message_type = 4;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> MessageTypeList {
-        get { return pbc::Lists.AsReadOnly(result.messageType_); }
+        get { return result.messageType_; }
       }
       public int MessageTypeCount {
         get { return result.MessageTypeCount; }
@@ -985,34 +942,25 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddMessageType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto value) {
-        if (result.messageType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.messageType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-        }
         result.messageType_.Add(value);
         return this;
       }
       public Builder AddMessageType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder builderForValue) {
-        if (result.messageType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.messageType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-        }
         result.messageType_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeMessageType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> values) {
-        if (result.messageType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.messageType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-        }
         base.AddRange(values, result.messageType_);
         return this;
       }
       public Builder ClearMessageType() {
-        result.messageType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty;
+        result.messageType_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList {
-        get { return pbc::Lists.AsReadOnly(result.enumType_); }
+        get { return result.enumType_; }
       }
       public int EnumTypeCount {
         get { return result.EnumTypeCount; }
@@ -1029,34 +977,25 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto value) {
-        if (result.enumType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-        }
         result.enumType_.Add(value);
         return this;
       }
       public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) {
-        if (result.enumType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-        }
         result.enumType_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeEnumType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> values) {
-        if (result.enumType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-        }
         base.AddRange(values, result.enumType_);
         return this;
       }
       public Builder ClearEnumType() {
-        result.enumType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty;
+        result.enumType_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.ServiceDescriptorProto service = 6;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> ServiceList {
-        get { return pbc::Lists.AsReadOnly(result.service_); }
+        get { return result.service_; }
       }
       public int ServiceCount {
         get { return result.ServiceCount; }
@@ -1073,34 +1012,25 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddService(global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto value) {
-        if (result.service_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>.Empty) {
-          result.service_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>();
-        }
         result.service_.Add(value);
         return this;
       }
       public Builder AddService(global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.Builder builderForValue) {
-        if (result.service_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>.Empty) {
-          result.service_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>();
-        }
         result.service_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeService(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto> values) {
-        if (result.service_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>.Empty) {
-          result.service_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>();
-        }
         base.AddRange(values, result.service_);
         return this;
       }
       public Builder ClearService() {
-        result.service_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto>.Empty;
+        result.service_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.FieldDescriptorProto extension = 7;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList {
-        get { return pbc::Lists.AsReadOnly(result.extension_); }
+        get { return result.extension_; }
       }
       public int ExtensionCount {
         get { return result.ExtensionCount; }
@@ -1117,28 +1047,19 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) {
-        if (result.extension_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         result.extension_.Add(value);
         return this;
       }
       public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) {
-        if (result.extension_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         result.extension_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeExtension(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> values) {
-        if (result.extension_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         base.AddRange(values, result.extension_);
         return this;
       }
       public Builder ClearExtension() {
-        result.extension_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty;
+        result.extension_.Clear();
         return this;
       }
       
@@ -1180,7 +1101,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class DescriptorProto : pb::GeneratedMessage<DescriptorProto, DescriptorProto.Builder> {
-    private static readonly DescriptorProto defaultInstance = new DescriptorProto();
+    private static readonly DescriptorProto defaultInstance = new Builder().BuildPartial();
     public static DescriptorProto DefaultInstance {
       get { return defaultInstance; }
     }
@@ -1204,7 +1125,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     #region Nested types
     public static class Types {
       public sealed partial class ExtensionRange : pb::GeneratedMessage<ExtensionRange, ExtensionRange.Builder> {
-        private static readonly ExtensionRange defaultInstance = new ExtensionRange();
+        private static readonly ExtensionRange defaultInstance = new Builder().BuildPartial();
         public static ExtensionRange DefaultInstance {
           get { return defaultInstance; }
         }
@@ -1466,7 +1387,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.FieldDescriptorProto field = 2;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> field_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> field_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> FieldList {
       get { return field_; } 
     }
@@ -1478,7 +1399,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.FieldDescriptorProto extension = 6;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> extension_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> extension_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList {
       get { return extension_; } 
     }
@@ -1490,7 +1411,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.DescriptorProto nested_type = 3;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> nestedType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> nestedType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> NestedTypeList {
       get { return nestedType_; } 
     }
@@ -1502,7 +1423,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> enumType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> enumType_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList {
       get { return enumType_; } 
     }
@@ -1514,7 +1435,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> extensionRange_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> extensionRange_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> ExtensionRangeList {
       get { return extensionRange_; } 
     }
@@ -1672,21 +1593,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto BuildPartial() {
-        if (result.field_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.field_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.AsReadOnly(result.field_);
-        }
-        if (result.extension_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.AsReadOnly(result.extension_);
-        }
-        if (result.nestedType_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.nestedType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.AsReadOnly(result.nestedType_);
-        }
-        if (result.enumType_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.AsReadOnly(result.enumType_);
-        }
-        if (result.extensionRange_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>.Empty) {
-          result.extensionRange_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>.AsReadOnly(result.extensionRange_);
-        }
+        result.field_.MakeReadOnly();
+        result.extension_.MakeReadOnly();
+        result.nestedType_.MakeReadOnly();
+        result.enumType_.MakeReadOnly();
+        result.extensionRange_.MakeReadOnly();
         global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto returnMe = result;
         result = null;
         return returnMe;
@@ -1707,33 +1618,18 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
           Name = other.Name;
         }
         if (other.field_.Count != 0) {
-          if (result.field_.Count == 0) {
-            result.field_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-          }
           base.AddRange(other.field_, result.field_);
         }
         if (other.extension_.Count != 0) {
-          if (result.extension_.Count == 0) {
-            result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-          }
           base.AddRange(other.extension_, result.extension_);
         }
         if (other.nestedType_.Count != 0) {
-          if (result.nestedType_.Count == 0) {
-            result.nestedType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-          }
           base.AddRange(other.nestedType_, result.nestedType_);
         }
         if (other.enumType_.Count != 0) {
-          if (result.enumType_.Count == 0) {
-            result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-          }
           base.AddRange(other.enumType_, result.enumType_);
         }
         if (other.extensionRange_.Count != 0) {
-          if (result.extensionRange_.Count == 0) {
-            result.extensionRange_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>();
-          }
           base.AddRange(other.extensionRange_, result.extensionRange_);
         }
         if (other.HasOptions) {
@@ -1833,7 +1729,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       // repeated .google.protobuf.FieldDescriptorProto field = 2;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> FieldList {
-        get { return pbc::Lists.AsReadOnly(result.field_); }
+        get { return result.field_; }
       }
       public int FieldCount {
         get { return result.FieldCount; }
@@ -1850,34 +1746,25 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddField(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) {
-        if (result.field_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.field_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         result.field_.Add(value);
         return this;
       }
       public Builder AddField(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) {
-        if (result.field_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.field_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         result.field_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeField(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> values) {
-        if (result.field_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.field_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         base.AddRange(values, result.field_);
         return this;
       }
       public Builder ClearField() {
-        result.field_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty;
+        result.field_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.FieldDescriptorProto extension = 6;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> ExtensionList {
-        get { return pbc::Lists.AsReadOnly(result.extension_); }
+        get { return result.extension_; }
       }
       public int ExtensionCount {
         get { return result.ExtensionCount; }
@@ -1894,34 +1781,25 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto value) {
-        if (result.extension_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         result.extension_.Add(value);
         return this;
       }
       public Builder AddExtension(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder builderForValue) {
-        if (result.extension_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         result.extension_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeExtension(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto> values) {
-        if (result.extension_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty) {
-          result.extension_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>();
-        }
         base.AddRange(values, result.extension_);
         return this;
       }
       public Builder ClearExtension() {
-        result.extension_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto>.Empty;
+        result.extension_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.DescriptorProto nested_type = 3;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> NestedTypeList {
-        get { return pbc::Lists.AsReadOnly(result.nestedType_); }
+        get { return result.nestedType_; }
       }
       public int NestedTypeCount {
         get { return result.NestedTypeCount; }
@@ -1938,34 +1816,25 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddNestedType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto value) {
-        if (result.nestedType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.nestedType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-        }
         result.nestedType_.Add(value);
         return this;
       }
       public Builder AddNestedType(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder builderForValue) {
-        if (result.nestedType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.nestedType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-        }
         result.nestedType_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeNestedType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto> values) {
-        if (result.nestedType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty) {
-          result.nestedType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>();
-        }
         base.AddRange(values, result.nestedType_);
         return this;
       }
       public Builder ClearNestedType() {
-        result.nestedType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto>.Empty;
+        result.nestedType_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> EnumTypeList {
-        get { return pbc::Lists.AsReadOnly(result.enumType_); }
+        get { return result.enumType_; }
       }
       public int EnumTypeCount {
         get { return result.EnumTypeCount; }
@@ -1982,34 +1851,25 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto value) {
-        if (result.enumType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-        }
         result.enumType_.Add(value);
         return this;
       }
       public Builder AddEnumType(global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder builderForValue) {
-        if (result.enumType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-        }
         result.enumType_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeEnumType(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto> values) {
-        if (result.enumType_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty) {
-          result.enumType_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>();
-        }
         base.AddRange(values, result.enumType_);
         return this;
       }
       public Builder ClearEnumType() {
-        result.enumType_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto>.Empty;
+        result.enumType_.Clear();
         return this;
       }
       
       // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> ExtensionRangeList {
-        get { return pbc::Lists.AsReadOnly(result.extensionRange_); }
+        get { return result.extensionRange_; }
       }
       public int ExtensionRangeCount {
         get { return result.ExtensionRangeCount; }
@@ -2026,28 +1886,19 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddExtensionRange(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange value) {
-        if (result.extensionRange_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>.Empty) {
-          result.extensionRange_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>();
-        }
         result.extensionRange_.Add(value);
         return this;
       }
       public Builder AddExtensionRange(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Builder builderForValue) {
-        if (result.extensionRange_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>.Empty) {
-          result.extensionRange_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>();
-        }
         result.extensionRange_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeExtensionRange(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange> values) {
-        if (result.extensionRange_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>.Empty) {
-          result.extensionRange_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>();
-        }
         base.AddRange(values, result.extensionRange_);
         return this;
       }
       public Builder ClearExtensionRange() {
-        result.extensionRange_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange>.Empty;
+        result.extensionRange_.Clear();
         return this;
       }
       
@@ -2089,7 +1940,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class FieldDescriptorProto : pb::GeneratedMessage<FieldDescriptorProto, FieldDescriptorProto.Builder> {
-    private static readonly FieldDescriptorProto defaultInstance = new FieldDescriptorProto();
+    private static readonly FieldDescriptorProto defaultInstance = new Builder().BuildPartial();
     public static FieldDescriptorProto DefaultInstance {
       get { return defaultInstance; }
     }
@@ -2651,7 +2502,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class EnumDescriptorProto : pb::GeneratedMessage<EnumDescriptorProto, EnumDescriptorProto.Builder> {
-    private static readonly EnumDescriptorProto defaultInstance = new EnumDescriptorProto();
+    private static readonly EnumDescriptorProto defaultInstance = new Builder().BuildPartial();
     public static EnumDescriptorProto DefaultInstance {
       get { return defaultInstance; }
     }
@@ -2683,7 +2534,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> value_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> value_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> ValueList {
       get { return value_; } 
     }
@@ -2817,9 +2668,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto BuildPartial() {
-        if (result.value_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>.Empty) {
-          result.value_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>.AsReadOnly(result.value_);
-        }
+        result.value_.MakeReadOnly();
         global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto returnMe = result;
         result = null;
         return returnMe;
@@ -2840,9 +2689,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
           Name = other.Name;
         }
         if (other.value_.Count != 0) {
-          if (result.value_.Count == 0) {
-            result.value_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>();
-          }
           base.AddRange(other.value_, result.value_);
         }
         if (other.HasOptions) {
@@ -2918,7 +2764,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> ValueList {
-        get { return pbc::Lists.AsReadOnly(result.value_); }
+        get { return result.value_; }
       }
       public int ValueCount {
         get { return result.ValueCount; }
@@ -2935,28 +2781,19 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddValue(global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto value) {
-        if (result.value_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>.Empty) {
-          result.value_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>();
-        }
         result.value_.Add(value);
         return this;
       }
       public Builder AddValue(global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.Builder builderForValue) {
-        if (result.value_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>.Empty) {
-          result.value_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>();
-        }
         result.value_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeValue(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto> values) {
-        if (result.value_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>.Empty) {
-          result.value_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>();
-        }
         base.AddRange(values, result.value_);
         return this;
       }
       public Builder ClearValue() {
-        result.value_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto>.Empty;
+        result.value_.Clear();
         return this;
       }
       
@@ -2998,7 +2835,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class EnumValueDescriptorProto : pb::GeneratedMessage<EnumValueDescriptorProto, EnumValueDescriptorProto.Builder> {
-    private static readonly EnumValueDescriptorProto defaultInstance = new EnumValueDescriptorProto();
+    private static readonly EnumValueDescriptorProto defaultInstance = new Builder().BuildPartial();
     public static EnumValueDescriptorProto DefaultInstance {
       get { return defaultInstance; }
     }
@@ -3310,7 +3147,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class ServiceDescriptorProto : pb::GeneratedMessage<ServiceDescriptorProto, ServiceDescriptorProto.Builder> {
-    private static readonly ServiceDescriptorProto defaultInstance = new ServiceDescriptorProto();
+    private static readonly ServiceDescriptorProto defaultInstance = new Builder().BuildPartial();
     public static ServiceDescriptorProto DefaultInstance {
       get { return defaultInstance; }
     }
@@ -3342,7 +3179,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
     }
     
     // repeated .google.protobuf.MethodDescriptorProto method = 2;
-    private scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> method_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>.Empty;
+    private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> method_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>();
     public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> MethodList {
       get { return method_; } 
     }
@@ -3476,9 +3313,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       }
       
       public override global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto BuildPartial() {
-        if (result.method_ != pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>.Empty) {
-          result.method_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>.AsReadOnly(result.method_);
-        }
+        result.method_.MakeReadOnly();
         global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto returnMe = result;
         result = null;
         return returnMe;
@@ -3499,9 +3334,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
           Name = other.Name;
         }
         if (other.method_.Count != 0) {
-          if (result.method_.Count == 0) {
-            result.method_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>();
-          }
           base.AddRange(other.method_, result.method_);
         }
         if (other.HasOptions) {
@@ -3577,7 +3409,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
       
       // repeated .google.protobuf.MethodDescriptorProto method = 2;
       public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> MethodList {
-        get { return pbc::Lists.AsReadOnly(result.method_); }
+        get { return result.method_; }
       }
       public int MethodCount {
         get { return result.MethodCount; }
@@ -3594,28 +3426,19 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
         return this;
       }
       public Builder AddMethod(global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto value) {
-        if (result.method_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>.Empty) {
-          result.method_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>();
-        }
         result.method_.Add(value);
         return this;
       }
       public Builder AddMethod(global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.Builder builderForValue) {
-        if (result.method_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>.Empty) {
-          result.method_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>();
-        }
         result.method_.Add(builderForValue.Build());
         return this;
       }
       public Builder AddRangeMethod(scg::IEnumerable<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto> values) {
-        if (result.method_ == pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>.Empty) {
-          result.method_ = new scg::List<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>();
-        }
         base.AddRange(values, result.method_);
         return this;
       }
       public Builder ClearMethod() {
-        result.method_ = pbc::Lists<global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto>.Empty;
+        result.method_.Clear();
         return this;
       }
       
@@ -3657,7 +3480,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class MethodDescriptorProto : pb::GeneratedMessage<MethodDescriptorProto, MethodDescriptorProto.Builder> {
-    private static readonly MethodDescriptorProto defaultInstance = new MethodDescriptorProto();
+    private static readonly MethodDescriptorProto defaultInstance = new Builder().BuildPartial();
     public static MethodDescriptorProto DefaultInstance {
       get { return defaultInstance; }
     }
@@ -4011,7 +3834,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class FileOptions : pb::GeneratedMessage<FileOptions, FileOptions.Builder> {
-    private static readonly FileOptions defaultInstance = new FileOptions();
+    private static readonly FileOptions defaultInstance = new Builder().BuildPartial();
     public static FileOptions DefaultInstance {
       get { return defaultInstance; }
     }
@@ -4568,7 +4391,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class MessageOptions : pb::GeneratedMessage<MessageOptions, MessageOptions.Builder> {
-    private static readonly MessageOptions defaultInstance = new MessageOptions();
+    private static readonly MessageOptions defaultInstance = new Builder().BuildPartial();
     public static MessageOptions DefaultInstance {
       get { return defaultInstance; }
     }
@@ -4775,7 +4598,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class FieldOptions : pb::GeneratedMessage<FieldOptions, FieldOptions.Builder> {
-    private static readonly FieldOptions defaultInstance = new FieldOptions();
+    private static readonly FieldOptions defaultInstance = new Builder().BuildPartial();
     public static FieldOptions DefaultInstance {
       get { return defaultInstance; }
     }
@@ -5038,7 +4861,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class EnumOptions : pb::GeneratedMessage<EnumOptions, EnumOptions.Builder> {
-    private static readonly EnumOptions defaultInstance = new EnumOptions();
+    private static readonly EnumOptions defaultInstance = new Builder().BuildPartial();
     public static EnumOptions DefaultInstance {
       get { return defaultInstance; }
     }
@@ -5203,7 +5026,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class EnumValueOptions : pb::GeneratedMessage<EnumValueOptions, EnumValueOptions.Builder> {
-    private static readonly EnumValueOptions defaultInstance = new EnumValueOptions();
+    private static readonly EnumValueOptions defaultInstance = new Builder().BuildPartial();
     public static EnumValueOptions DefaultInstance {
       get { return defaultInstance; }
     }
@@ -5368,7 +5191,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class ServiceOptions : pb::GeneratedMessage<ServiceOptions, ServiceOptions.Builder> {
-    private static readonly ServiceOptions defaultInstance = new ServiceOptions();
+    private static readonly ServiceOptions defaultInstance = new Builder().BuildPartial();
     public static ServiceOptions DefaultInstance {
       get { return defaultInstance; }
     }
@@ -5533,7 +5356,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
   }
   
   public sealed partial class MethodOptions : pb::GeneratedMessage<MethodOptions, MethodOptions.Builder> {
-    private static readonly MethodOptions defaultInstance = new MethodOptions();
+    private static readonly MethodOptions defaultInstance = new Builder().BuildPartial();
     public static MethodOptions DefaultInstance {
       get { return defaultInstance; }
     }

+ 0 - 26
csharp/ProtocolBuffers/FieldAccess/Delegates.cs

@@ -1,26 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.
-// http://code.google.com/p/protobuf/
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-namespace Google.ProtocolBuffers.FieldAccess {
-
-  // These delegate declarations mirror the ones in .NET 3.5 for the sake of familiarity.
-  internal delegate TResult Func<TResult>();
-  internal delegate TResult Func<T, TResult>(T arg);
-  internal delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
-  internal delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
-  internal delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4); 
-  internal delegate void Action<T1, T2>(T1 arg1, T2 arg2);
-}

+ 87 - 61
csharp/ProtocolBuffers/MessageStreamIterator.cs

@@ -8,25 +8,67 @@ using System.Reflection;
 namespace Google.ProtocolBuffers {
 
   /// <summary>
-  /// Helper class to create MessageStreamIterators without explicitly specifying
-  /// the builder type. The concrete builder type is determined by reflection, based
-  /// on the message type. The reflection step looks for a <c>CreateBuilder</c> method
-  /// in the message type which is public and static, and uses the return type of that
-  /// method as the builder type. This will work for all generated messages, whether
-  /// optimised for size or speed. It won't work for dynamic messages.
-  /// 
-  /// TODO(jonskeet): This also won't work for non-public protos :(
-  /// Pass in delegate to create a builder?
+  /// Iterates over data created using a <see cref="MessageStreamWriter{T}" />.
+  /// Unlike MessageStreamWriter, this class is not usually constructed directly with
+  /// a stream; instead it is provided with a way of opening a stream when iteration
+  /// is started. The stream is closed when the iteration is completed or the enumerator
+  /// is disposed. (This occurs naturally when using <c>foreach</c>.)
   /// </summary>
-  public static class MessageStreamIterator {
+  public class MessageStreamIterator<TMessage> : IEnumerable<TMessage>
+      where TMessage : IMessage<TMessage> {
+
+    private readonly StreamProvider streamProvider;
+    private readonly ExtensionRegistry extensionRegistry;
+
+    /// <summary>
+    /// Delegate created via reflection trickery (once per type) to create a builder
+    /// and read a message from a CodedInputStream with it. Note that unlike in Java,
+    /// there's one static field per constructed type.
+    /// </summary>
+    private static readonly Func<CodedInputStream, ExtensionRegistry, TMessage> messageReader = BuildMessageReader();
+
+    /// <summary>
+    /// Any exception (within reason) thrown within messageReader is caught and rethrown in the constructor.
+    /// This makes life a lot simpler for the caller.
+    /// </summary>
+    private static Exception typeInitializationException;
+
+    /// <summary>
+    /// Creates the delegate later used to read messages. This is only called once per type, but to
+    /// avoid exceptions occurring at confusing times, if this fails it will set typeInitializationException
+    /// to the appropriate error and return null.
+    /// </summary>
+    private static Func<CodedInputStream, ExtensionRegistry, TMessage> BuildMessageReader() {
+      try {
+        Type builderType = FindBuilderType();
+
+        // Yes, it's redundant to find this again, but it's only the once...
+        MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", Type.EmptyTypes);
+        Delegate builderBuilder = Delegate.CreateDelegate(
+            typeof(Func<>).MakeGenericType(builderType), null, createBuilderMethod);
 
-    public static IEnumerable<TMessage> FromFile<TMessage>(string file) 
-        where TMessage : IMessage<TMessage> {
-      return FromStreamProvider<TMessage>(() => File.OpenRead(file));
+        MethodInfo buildMethod = typeof(MessageStreamIterator<TMessage>)
+            .GetMethod("BuildImpl", BindingFlags.Static | BindingFlags.NonPublic)
+            .MakeGenericMethod(typeof(TMessage), builderType);
+
+        return (Func<CodedInputStream, ExtensionRegistry, TMessage>)Delegate.CreateDelegate(
+          typeof(Func<CodedInputStream, ExtensionRegistry, TMessage>), builderBuilder, buildMethod);
+      } catch (ArgumentException e) {
+        typeInitializationException = e;
+      } catch (InvalidOperationException e) {
+        typeInitializationException = e;
+      } catch (InvalidCastException e) {
+        // Can't see why this would happen, but best to know about it.
+        typeInitializationException = e;
+      }
+      return null;
     }
 
-    public static IEnumerable<TMessage> FromStreamProvider<TMessage>(StreamProvider streamProvider)
-        where TMessage : IMessage<TMessage> {
+    /// <summary>
+    /// Works out the builder type for TMessage, or throws an ArgumentException to explain why it can't.
+    /// This will check 
+    /// </summary>
+    private static Type FindBuilderType() {
       MethodInfo createBuilderMethod = typeof(TMessage).GetMethod("CreateBuilder", Type.EmptyTypes);
       if (createBuilderMethod == null) {
         throw new ArgumentException("Message type " + typeof(TMessage).FullName + " has no CreateBuilder method.");
@@ -35,68 +77,57 @@ namespace Google.ProtocolBuffers {
         throw new ArgumentException("CreateBuilder method in " + typeof(TMessage).FullName + " has void return type");
       }
       Type builderType = createBuilderMethod.ReturnType;
-      if (builderType.GetConstructor(Type.EmptyTypes) == null) {
-        throw new ArgumentException("Builder type " + builderType.FullName + " has no public parameterless constructor.");
-      }
       Type messageInterface = typeof(IMessage<,>).MakeGenericType(typeof(TMessage), builderType);
       Type builderInterface = typeof(IBuilder<,>).MakeGenericType(typeof(TMessage), builderType);
-      if (Array.IndexOf(typeof (TMessage).GetInterfaces(), messageInterface) == -1) {
+      if (Array.IndexOf(typeof(TMessage).GetInterfaces(), messageInterface) == -1) {
         throw new ArgumentException("Message type " + typeof(TMessage) + " doesn't implement " + messageInterface.FullName);
       }
       if (Array.IndexOf(builderType.GetInterfaces(), builderInterface) == -1) {
         throw new ArgumentException("Builder type " + typeof(TMessage) + " doesn't implement " + builderInterface.FullName);
       }
-      Type iteratorType = typeof(MessageStreamIterator<,>).MakeGenericType(typeof(TMessage), builderType);
-      MethodInfo factoryMethod = iteratorType.GetMethod("FromStreamProvider", new Type[] { typeof(StreamProvider) });
-      return (IEnumerable<TMessage>) factoryMethod.Invoke(null, new object[] { streamProvider });
+      return builderType;
     }
-  }
 
-  /// <summary>
-  /// Iterates over data created using a <see cref="MessageStreamWriter{T}" />.
-  /// Unlike MessageStreamWriter, this class is not usually constructed directly with
-  /// a stream; instead it is provided with a way of opening a stream when iteration
-  /// is started. The stream is closed when the iteration is completed or the enumerator
-  /// is disposed. (This occurs naturally when using <c>foreach</c>.)
-  /// This type is generic in both the message type and the builder type; if only the
-  /// iteration is required (i.e. just <see cref="IEnumerable{T}" />) then the static
-  /// generic methods in the nongeneric class are more appropriate.
-  /// </summary>
-  public sealed class MessageStreamIterator<TMessage, TBuilder> : IEnumerable<TMessage> 
-      where TMessage : IMessage<TMessage, TBuilder>
-      where TBuilder : IBuilder<TMessage, TBuilder>, new() {
-
-    private readonly StreamProvider streamProvider;
-    private readonly ExtensionRegistry extensionRegistry;
+    /// <summary>
+    /// Method we'll use to build messageReader, with the first parameter fixed to TMessage.CreateBuilder. Note that we
+    /// have to introduce another type parameter (TMessage2) as we can't constrain TMessage for just a single method
+    /// (and we can't do it at the type level because we don't know TBuilder). However, by constraining TMessage2
+    /// to not only implement IMessage appropriately but also to derive from TMessage2, we can avoid doing a cast
+    /// for every message; the implicit reference conversion will be fine. In practice, TMessage2 and TMessage will
+    /// be the same type when we construct the generic method by reflection.
+    /// </summary>
+    private static TMessage BuildImpl<TMessage2, TBuilder>(Func<TBuilder> builderBuilder, CodedInputStream input, ExtensionRegistry registry) 
+        where TBuilder : IBuilder<TMessage2, TBuilder>
+        where TMessage2 : TMessage, IMessage<TMessage2, TBuilder> {
+      TBuilder builder = builderBuilder();
+      input.ReadMessage(builder, registry);
+      return builder.Build();
+    }
+    
     private static readonly uint ExpectedTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
 
     private MessageStreamIterator(StreamProvider streamProvider, ExtensionRegistry extensionRegistry) {
+      if (messageReader == null) {
+        throw typeInitializationException;
+      }
       this.streamProvider = streamProvider;
       this.extensionRegistry = extensionRegistry;
     }
 
     /// <summary>
-    /// Creates an instance which opens the specified file when it begins
-    /// iterating. No extension registry is used when reading messages.
+    /// Creates a new instance which uses the same stream provider as this one,
+    /// but the specified extension registry.
     /// </summary>
-    public static MessageStreamIterator<TMessage, TBuilder> FromFile(string file) {
-      return new MessageStreamIterator<TMessage, TBuilder>(() => File.OpenRead(file), ExtensionRegistry.Empty);
+    public MessageStreamIterator<TMessage> WithExtensionRegistry(ExtensionRegistry newRegistry) {
+      return new MessageStreamIterator<TMessage>(streamProvider, newRegistry);
     }
 
-    /// <summary>
-    /// Creates an instance which calls the given delegate when it begins
-    /// iterating. No extension registry is used when reading messages.
-    /// </summary>
-    public static MessageStreamIterator<TMessage, TBuilder> FromStreamProvider(StreamProvider streamProvider) {
-      return new MessageStreamIterator<TMessage, TBuilder>(streamProvider, ExtensionRegistry.Empty);
+    public static MessageStreamIterator<TMessage> FromFile(string file) {
+      return new MessageStreamIterator<TMessage>(() => File.OpenRead(file), ExtensionRegistry.Empty);
     }
 
-    /// <summary>
-    /// Creates a new instance which uses the same stream provider as this one,
-    /// but the specified extension registry.
-    /// </summary>
-    public MessageStreamIterator<TMessage, TBuilder> WithExtensionRegistry(ExtensionRegistry newRegistry) {
-      return new MessageStreamIterator<TMessage, TBuilder>(streamProvider, newRegistry);
+    public static MessageStreamIterator<TMessage> FromStreamProvider(StreamProvider streamProvider) {
+      return new MessageStreamIterator<TMessage>(streamProvider, ExtensionRegistry.Empty);
     }
 
     public IEnumerator<TMessage> GetEnumerator() {
@@ -107,16 +138,11 @@ namespace Google.ProtocolBuffers {
           if (tag != ExpectedTag) {
             throw InvalidProtocolBufferException.InvalidMessageStreamTag();
           }
-          TBuilder builder = new TBuilder();
-          input.ReadMessage(builder, extensionRegistry);
-          yield return builder.Build();
+          yield return messageReader(input, extensionRegistry);
         }
       }
     }
 
-    /// <summary>
-    /// Explicit implementation of nongeneric IEnumerable interface.
-    /// </summary>
     IEnumerator IEnumerable.GetEnumerator() {
       return GetEnumerator();
     }

+ 1 - 1
csharp/ProtocolBuffers/ProtocolBuffers.csproj

@@ -41,6 +41,7 @@
     <Compile Include="AbstractBuilder.cs" />
     <Compile Include="AbstractMessage.cs" />
     <Compile Include="ByteString.cs" />
+    <Compile Include="Collections\PopsicleList.cs" />
     <Compile Include="Delegates.cs" />
     <Compile Include="CodedInputStream.cs" />
     <Compile Include="CodedOutputStream.cs" />
@@ -72,7 +73,6 @@
     <Compile Include="ExtendableMessage.cs" />
     <Compile Include="ExtensionInfo.cs" />
     <Compile Include="ExtensionRegistry.cs" />
-    <Compile Include="FieldAccess\Delegates.cs" />
     <Compile Include="FieldAccess\ReflectionUtil.cs" />
     <Compile Include="FieldAccess\SingleEnumAccessor.cs" />
     <Compile Include="FieldAccess\SingleMessageAccessor.cs" />

+ 2 - 1
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -212,7 +212,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
   }
   printer->Indent();
   printer->Print(
-    "private static readonly $classname$ defaultInstance = new $classname$();\r\n"
+    // Must call Build() to make sure all lists are made read-only
+    "private static readonly $classname$ defaultInstance = new Builder().BuildPartial();\r\n"
     "public static $classname$ DefaultInstance {\r\n"
     "  get { return defaultInstance; }\r\n"
     "}\r\n"

+ 7 - 23
src/google/protobuf/compiler/csharp/csharp_message_field.cc

@@ -175,9 +175,9 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 void RepeatedMessageFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private scg::IList<$type$> $name$_ = pbc::Lists<$type$>.Empty;\r\n"
+    "private pbc::PopsicleList<$type$> $name$_ = new pbc::PopsicleList<$type$>();\r\n"
     "public scg::IList<$type$> $capitalized_name$List {\r\n"
-    "  get { return $name$_; } \r\n"   // note:  unmodifiable list
+    "  get { return $name$_; } \r\n"   // Will be unmodifiable by the time it's exposed
     "}\r\n"
     "public int $capitalized_name$Count\r\n"
     "  { get { return $name$_.Count; }\r\n"
@@ -190,12 +190,10 @@ GenerateMembers(io::Printer* printer) const {
 void RepeatedMessageFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    // Note:  We return an unmodifiable list because otherwise the caller
-    //   could hold on to the returned list and modify it after the message
-    //   has been built, thus mutating the message which is supposed to be
-    //   immutable.
+    // Note:  We can return the original list here, because we
+    // make it read-only when we build.
     "public scg::IList<$type$> $capitalized_name$List {\r\n"
-    "  get { return pbc::Lists.AsReadOnly(result.$name$_); }\r\n"
+    "  get { return result.$name$_; }\r\n"
     "}\r\n"
     "public int $capitalized_name$Count {\r\n"
     "  get { return result.$capitalized_name$Count; }\r\n"
@@ -212,28 +210,19 @@ GenerateBuilderMembers(io::Printer* printer) const {
     "  return this;\r\n"
     "}\r\n"
     "public Builder Add$capitalized_name$($type$ value) {\r\n"
-    "  if (result.$name$_ == pbc::Lists<$type$>.Empty) {\r\n"
-    "    result.$name$_ = new scg::List<$type$>();\r\n"
-    "  }\r\n"
     "  result.$name$_.Add(value);\r\n"
     "  return this;\r\n"
     "}\r\n"
     "public Builder Add$capitalized_name$($type$.Builder builderForValue) {\r\n"
-    "  if (result.$name$_ == pbc::Lists<$type$>.Empty) {\r\n"
-    "    result.$name$_ = new scg::List<$type$>();\r\n"
-    "  }\r\n"
     "  result.$name$_.Add(builderForValue.Build());\r\n"
     "  return this;\r\n"
     "}\r\n"
     "public Builder AddRange$capitalized_name$(scg::IEnumerable<$type$> values) {\r\n"
-    "  if (result.$name$_ == pbc::Lists<$type$>.Empty) {\r\n"
-    "    result.$name$_ = new scg::List<$type$>();\r\n"
-    "  }\r\n"
     "  base.AddRange(values, result.$name$_);\r\n"
     "  return this;\r\n"
     "}\r\n"
     "public Builder Clear$capitalized_name$() {\r\n"
-    "  result.$name$_ = pbc::Lists<$type$>.Empty;\r\n"
+    "  result.$name$_.Clear();\r\n"
     "  return this;\r\n"
     "}\r\n");
 }
@@ -242,9 +231,6 @@ void RepeatedMessageFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (other.$name$_.Count != 0) {\r\n"
-    "  if (result.$name$_.Count == 0) {\r\n"
-    "    result.$name$_ = new scg::List<$type$>();\r\n"
-    "  }\r\n"
     "  base.AddRange(other.$name$_, result.$name$_);\r\n"
     "}\r\n");
 }
@@ -252,9 +238,7 @@ GenerateMergingCode(io::Printer* printer) const {
 void RepeatedMessageFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "if (result.$name$_ != pbc::Lists<$type$>.Empty) {\r\n"
-    "  result.$name$_ = pbc::Lists<$type$>.AsReadOnly(result.$name$_);\r\n"
-    "}\r\n");
+    "result.$name$_.MakeReadOnly();\r\n");
 }
 
 void RepeatedMessageFieldGenerator::

+ 7 - 18
src/google/protobuf/compiler/csharp/csharp_primitive_field.cc

@@ -239,9 +239,9 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
 void RepeatedPrimitiveFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private scg::IList<$type$> $name$_ = pbc::Lists<$type$>.Empty;\r\n"
+    "private pbc::PopsicleList<$type$> $name$_ = new pbc::PopsicleList<$type$>();\r\n"
     "public scg::IList<$type$> $capitalized_name$List {\r\n"
-    "  get { return $name$_; }\r\n"   // note:  unmodifiable list
+    "  get { return $name$_; } \r\n"   // Will be unmodifiable by the time it's exposed
     "}\r\n"
     "public int $capitalized_name$Count {\r\n"
     "  get { return $name$_.Count; }\r\n"
@@ -254,12 +254,10 @@ GenerateMembers(io::Printer* printer) const {
 void RepeatedPrimitiveFieldGenerator::
 GenerateBuilderMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    // Note:  We return an unmodifiable list because otherwise the caller
-    //   could hold on to the returned list and modify it after the message
-    //   has been built, thus mutating the message which is supposed to be
-    //   immutable. This unfortunately limits the use for collection initializers...
+    // Note:  We can return the original list here, because we
+    // make it read-only when we build.
     "public scg::IList<$type$> $capitalized_name$List {\r\n"
-    "  get { return pbc::Lists<$type$>.AsReadOnly(result.$name$_); }\r\n"
+    "  get { return result.$name$_; }\r\n"
     "}\r\n"
     "public int $capitalized_name$Count {\r\n"
     "  get { return result.$capitalized_name$Count; }\r\n"
@@ -272,21 +270,15 @@ GenerateBuilderMembers(io::Printer* printer) const {
     "  return this;\r\n"
     "}\r\n"
     "public Builder Add$capitalized_name$($type$ value) {\r\n"
-    "  if (result.$name$_.Count == 0) {\r\n"
-    "    result.$name$_ = new scg::List<$type$>();\r\n"
-    "  }\r\n"
     "  result.$name$_.Add(value);\r\n"
     "  return this;\r\n"
     "}\r\n"
     "public Builder AddRange$capitalized_name$(scg::IEnumerable<$type$> values) {\r\n"
-    "  if (result.$name$_.Count == 0) {\r\n"
-    "    result.$name$_ = new scg::List<$type$>();\r\n"
-    "  }\r\n"
     "  base.AddRange(values, result.$name$_);\r\n"
     "  return this;\r\n"
     "}\r\n"
     "public Builder Clear$capitalized_name$() {\r\n"
-    "  result.$name$_ = pbc::Lists<$type$>.Empty;\r\n"
+    "  result.$name$_.Clear();\r\n"
     "  return this;\r\n"
     "}\r\n");
 }
@@ -295,9 +287,6 @@ void RepeatedPrimitiveFieldGenerator::
 GenerateMergingCode(io::Printer* printer) const {
   printer->Print(variables_,
     "if (other.$name$_.Count != 0) {\r\n"
-    "  if (result.$name$_.Count == 0) {\r\n"
-    "    result.$name$_ = new scg::List<$type$>();\r\n"
-    "  }\r\n"
     "  base.AddRange(other.$name$_, result.$name$_);\r\n"
     "}\r\n");
 }
@@ -305,7 +294,7 @@ GenerateMergingCode(io::Printer* printer) const {
 void RepeatedPrimitiveFieldGenerator::
 GenerateBuildingCode(io::Printer* printer) const {
   printer->Print(variables_,
-    "result.$name$_ = pbc::Lists<$type$>.AsReadOnly(result.$name$_);\r\n");
+    "result.$name$_.MakeReadOnly();\r\n");
 }
 
 void RepeatedPrimitiveFieldGenerator::

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