Browse Source

Merge pull request #691 from jskeet/xml-documentation

Document everything, and turn on errors if we fail to document anything in the future
Jon Skeet 10 years ago
parent
commit
d77d70d227
27 changed files with 742 additions and 108 deletions
  1. 69 5
      csharp/src/Google.Protobuf/ByteString.cs
  2. 1 1
      csharp/src/Google.Protobuf/CodedInputStream.cs
  3. 7 0
      csharp/src/Google.Protobuf/CodedOutputStream.cs
  4. 137 4
      csharp/src/Google.Protobuf/Collections/MapField.cs
  5. 109 2
      csharp/src/Google.Protobuf/Collections/RepeatedField.cs
  6. 107 0
      csharp/src/Google.Protobuf/FieldCodec.cs
  7. 9 3
      csharp/src/Google.Protobuf/Google.Protobuf.csproj
  8. 2 1
      csharp/src/Google.Protobuf/IMessage.cs
  9. 5 2
      csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
  10. 13 0
      csharp/src/Google.Protobuf/JsonFormatter.cs
  11. 44 0
      csharp/src/Google.Protobuf/MessageExtensions.cs
  12. 24 0
      csharp/src/Google.Protobuf/MessageParser.cs
  13. 1 1
      csharp/src/Google.Protobuf/Preconditions.cs
  14. 3 0
      csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs
  15. 10 1
      csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
  16. 32 5
      csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
  17. 55 2
      csharp/src/Google.Protobuf/Reflection/FieldType.cs
  18. 8 13
      csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
  19. 11 0
      csharp/src/Google.Protobuf/Reflection/IDescriptor.cs
  20. 4 1
      csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs
  21. 4 2
      csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
  22. 6 0
      csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs
  23. 24 1
      csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
  24. 6 0
      csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
  25. 19 0
      csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs
  26. 5 2
      csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
  27. 27 62
      csharp/src/Google.Protobuf/WireFormat.cs

+ 69 - 5
csharp/src/Google.Protobuf/ByteString.cs

@@ -105,23 +105,35 @@ namespace Google.Protobuf
             get { return bytes.Length; }
         }
 
+        /// <summary>
+        /// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
+        /// </summary>
         public bool IsEmpty
         {
             get { return Length == 0; }
         }
 
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a byte array.
+        /// </summary>
+        /// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
+        /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
         public byte[] ToByteArray()
         {
             return (byte[]) bytes.Clone();
         }
 
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a standard base64 representation.
+        /// </summary>
+        /// <returns>A base64 representation of this <c>ByteString</c>.</returns>
         public string ToBase64()
         {
             return Convert.ToBase64String(bytes);
         }
 
         /// <summary>
-        /// Constructs a ByteString from the Base64 Encoded String.
+        /// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
         /// </summary>
         public static ByteString FromBase64(string bytes)
         {
@@ -131,7 +143,7 @@ namespace Google.Protobuf
         }
 
         /// <summary>
-        /// Constructs a ByteString from the given array. The contents
+        /// Constructs a <see cref="ByteString" /> from the given array. The contents
         /// are copied, so further modifications to the array will not
         /// be reflected in the returned ByteString.
         /// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form
@@ -143,7 +155,7 @@ namespace Google.Protobuf
         }
 
         /// <summary>
-        /// Constructs a ByteString from a portion of a byte array.
+        /// Constructs a <see cref="ByteString" /> from a portion of a byte array.
         /// </summary>
         public static ByteString CopyFrom(byte[] bytes, int offset, int count)
         {
@@ -153,7 +165,7 @@ namespace Google.Protobuf
         }
 
         /// <summary>
-        /// Creates a new ByteString by encoding the specified text with
+        /// Creates a new <see cref="ByteString" /> by encoding the specified text with
         /// the given encoding.
         /// </summary>
         public static ByteString CopyFrom(string text, Encoding encoding)
@@ -162,7 +174,7 @@ namespace Google.Protobuf
         }
 
         /// <summary>
-        /// Creates a new ByteString by encoding the specified text in UTF-8.
+        /// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
         /// </summary>
         public static ByteString CopyFromUtf8(string text)
         {
@@ -177,21 +189,46 @@ namespace Google.Protobuf
             get { return bytes[index]; }
         }
 
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
+        /// </summary>
+        /// <remarks>
+        /// This method should only be used to convert binary data which was the result of encoding
+        /// text with the given encoding.
+        /// </remarks>
+        /// <param name="encoding">The encoding to use to decode the binary data into text.</param>
+        /// <returns>The result of decoding the binary data with the given decoding.</returns>
         public string ToString(Encoding encoding)
         {
             return encoding.GetString(bytes, 0, bytes.Length);
         }
 
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
+        /// </summary>
+        /// <remarks>
+        /// This method should only be used to convert binary data which was the result of encoding
+        /// text with UTF-8.
+        /// </remarks>
+        /// <returns>The result of decoding the binary data with the given decoding.</returns>
         public string ToStringUtf8()
         {
             return ToString(Encoding.UTF8);
         }
 
+        /// <summary>
+        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+        /// </summary>
+        /// <returns>An iterator over the bytes in this object.</returns>
         public IEnumerator<byte> GetEnumerator()
         {
             return ((IEnumerable<byte>) bytes).GetEnumerator();
         }
 
+        /// <summary>
+        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+        /// </summary>
+        /// <returns>An iterator over the bytes in this object.</returns>
         IEnumerator IEnumerable.GetEnumerator()
         {
             return GetEnumerator();
@@ -206,6 +243,12 @@ namespace Google.Protobuf
             return new CodedInputStream(bytes);
         }
 
+        /// <summary>
+        /// Compares two byte strings for equality.
+        /// </summary>
+        /// <param name="lhs">The first byte string to compare.</param>
+        /// <param name="rhs">The second byte string to compare.</param>
+        /// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
         public static bool operator ==(ByteString lhs, ByteString rhs)
         {
             if (ReferenceEquals(lhs, rhs))
@@ -230,6 +273,12 @@ namespace Google.Protobuf
             return true;
         }
 
+        /// <summary>
+        /// Compares two byte strings for inequality.
+        /// </summary>
+        /// <param name="lhs">The first byte string to compare.</param>
+        /// <param name="rhs">The second byte string to compare.</param>
+        /// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
         public static bool operator !=(ByteString lhs, ByteString rhs)
         {
             return !(lhs == rhs);
@@ -237,11 +286,21 @@ namespace Google.Protobuf
 
         // TODO(jonskeet): CopyTo if it turns out to be required
 
+        /// <summary>
+        /// Compares this byte string with another object.
+        /// </summary>
+        /// <param name="obj">The object to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
         public override bool Equals(object obj)
         {
             return this == (obj as ByteString);
         }
 
+        /// <summary>
+        /// Returns a hash code for this object. Two equal byte strings
+        /// will return the same hash code.
+        /// </summary>
+        /// <returns>A hash code for this object.</returns>
         public override int GetHashCode()
         {
             int ret = 23;
@@ -252,6 +311,11 @@ namespace Google.Protobuf
             return ret;
         }
 
+        /// <summary>
+        /// Compares this byte string with another.
+        /// </summary>
+        /// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
         public bool Equals(ByteString other)
         {
             return this == other;

+ 1 - 1
csharp/src/Google.Protobuf/CodedInputStream.cs

@@ -66,7 +66,7 @@ namespace Google.Protobuf
 
         internal const int DefaultRecursionLimit = 64;
         internal const int DefaultSizeLimit = 64 << 20; // 64MB
-        public const int BufferSize = 4096;
+        internal const int BufferSize = 4096;
 
         /// <summary>
         /// The total number of bytes read before the current buffer. The

+ 7 - 0
csharp/src/Google.Protobuf/CodedOutputStream.cs

@@ -297,6 +297,10 @@ namespace Google.Protobuf
             WriteInt32(value);
         }
 
+        /// <summary>
+        /// Writes an sfixed32 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
         public void WriteSFixed32(int value)
         {
             WriteRawLittleEndian32((uint) value);
@@ -649,6 +653,9 @@ namespace Google.Protobuf
             }
         }
 
+        /// <summary>
+        /// Flushes any buffered data to the underlying stream (if there is one).
+        /// </summary>
         public void Flush()
         {
             if (output != null)

+ 137 - 4
csharp/src/Google.Protobuf/Collections/MapField.cs

@@ -42,14 +42,14 @@ namespace Google.Protobuf.Collections
     /// <summary>
     /// Representation of a map field in a Protocol Buffer message.
     /// </summary>
+    /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
+    /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
     /// <remarks>
     /// This implementation preserves insertion order for simplicity of testing
     /// code using maps fields. Overwriting an existing entry does not change the
     /// position of that entry within the map. Equality is not order-sensitive.
-    /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal"/>.
+    /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal" />.
     /// </remarks>
-    /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
-    /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
     public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
     {
         // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
@@ -81,6 +81,12 @@ namespace Google.Protobuf.Collections
             this.allowNullValues = allowNullValues;
         }
 
+        /// <summary>
+        /// Creates a deep clone of this object.
+        /// </summary>
+        /// <returns>
+        /// A deep clone of this object.
+        /// </returns>
         public MapField<TKey, TValue> Clone()
         {
             var clone = new MapField<TKey, TValue>(allowNullValues);
@@ -100,6 +106,15 @@ namespace Google.Protobuf.Collections
             return clone;
         }
 
+        /// <summary>
+        /// Adds the specified key/value pair to the map.
+        /// </summary>
+        /// <remarks>
+        /// This operation fails if the key already exists in the map. To replace an existing entry, use the indexer.
+        /// </remarks>
+        /// <param name="key">The key to add</param>
+        /// <param name="value">The value to add.</param>
+        /// <exception cref="System.ArgumentException">The given key already exists in map.</exception>
         public void Add(TKey key, TValue value)
         {
             // Validation of arguments happens in ContainsKey and the indexer
@@ -110,12 +125,22 @@ namespace Google.Protobuf.Collections
             this[key] = value;
         }
 
+        /// <summary>
+        /// Determines whether the specified key is present in the map.
+        /// </summary>
+        /// <param name="key">The key to check.</param>
+        /// <returns><c>true</c> if the map contains the given key; <c>false</c> otherwise.</returns>
         public bool ContainsKey(TKey key)
         {
             Preconditions.CheckNotNullUnconstrained(key, "key");
             return map.ContainsKey(key);
         }
 
+        /// <summary>
+        /// Removes the entry identified by the given key from the map.
+        /// </summary>
+        /// <param name="key">The key indicating the entry to remove from the map.</param>
+        /// <returns><c>true</c> if the map contained the given key before the entry was removed; <c>false</c> otherwise.</returns>
         public bool Remove(TKey key)
         {
             Preconditions.CheckNotNullUnconstrained(key, "key");
@@ -132,6 +157,14 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Gets the value associated with the specified key.
+        /// </summary>
+        /// <param name="key">The key whose value to get.</param>
+        /// <param name="value">When this method returns, the value associated with the specified key, if the key is found;
+        /// otherwise, the default value for the type of the <paramref name="value"/> parameter.
+        /// This parameter is passed uninitialized.</param>
+        /// <returns><c>true</c> if the map contains an element with the specified key; otherwise, <c>false</c>.</returns>
         public bool TryGetValue(TKey key, out TValue value)
         {
             LinkedListNode<KeyValuePair<TKey, TValue>> node;
@@ -147,6 +180,13 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Gets or sets the value associated with the specified key.
+        /// </summary>
+        /// <param name="key">The key of the value to get or set.</param>
+        /// <exception cref="KeyNotFoundException">The property is retrieved and key does not exist in the collection.</exception>
+        /// <returns>The value associated with the specified key. If the specified key is not found,
+        /// a get operation throws a <see cref="KeyNotFoundException"/>, and a set operation creates a new element with the specified key.</returns>
         public TValue this[TKey key]
         {
             get
@@ -182,9 +222,21 @@ namespace Google.Protobuf.Collections
         }
 
         // TODO: Make these views?
+
+        /// <summary>
+        /// Gets a collection containing the keys in the map.
+        /// </summary>
         public ICollection<TKey> Keys { get { return list.Select(t => t.Key).ToList(); } }
+
+        /// <summary>
+        /// Gets a collection containing the values in the map.
+        /// </summary>
         public ICollection<TValue> Values { get { return list.Select(t => t.Value).ToList(); } }
 
+        /// <summary>
+        /// Adds the specified entries to the map.
+        /// </summary>
+        /// <param name="entries">The entries to add to the map.</param>
         public void Add(IDictionary<TKey, TValue> entries)
         {
             Preconditions.CheckNotNull(entries, "entries");
@@ -194,27 +246,51 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Returns an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>
+        /// An enumerator that can be used to iterate through the collection.
+        /// </returns>
         public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
         {
             return list.GetEnumerator();
         }
 
+        /// <summary>
+        /// Returns an enumerator that iterates through a collection.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
+        /// </returns>
         IEnumerator IEnumerable.GetEnumerator()
         {
             return GetEnumerator();
         }
 
+        /// <summary>
+        /// Adds the specified item to the map.
+        /// </summary>
+        /// <param name="item">The item to add to the map.</param>
         void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
         {
             Add(item.Key, item.Value);
         }
 
+        /// <summary>
+        /// Removes all items from the map.
+        /// </summary>
         public void Clear()
         {
             list.Clear();
             map.Clear();
         }
 
+        /// <summary>
+        /// Determines whether map contains an entry equivalent to the given key/value pair.
+        /// </summary>
+        /// <param name="item">The key/value pair to find.</param>
+        /// <returns></returns>
         bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
         {
             TValue value;
@@ -222,11 +298,22 @@ namespace Google.Protobuf.Collections
                 && EqualityComparer<TValue>.Default.Equals(item.Value, value);
         }
 
+        /// <summary>
+        /// Copies the key/value pairs in this map to an array.
+        /// </summary>
+        /// <param name="array">The array to copy the entries into.</param>
+        /// <param name="arrayIndex">The index of the array at which to start copying values.</param>
         void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
         {
             list.CopyTo(array, arrayIndex);
         }
 
+        /// <summary>
+        /// Removes the specified key/value pair from the map.
+        /// </summary>
+        /// <remarks>Both the key and the value must be found for the entry to be removed.</remarks>
+        /// <param name="item">The key/value pair to remove.</param>
+        /// <returns><c>true</c> if the key/value pair was found and removed; <c>false</c> otherwise.</returns>
         bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
         {
             if (item.Key == null)
@@ -252,14 +339,34 @@ namespace Google.Protobuf.Collections
         /// </summary>
         public bool AllowsNullValues { get { return allowNullValues; } }
 
+        /// <summary>
+        /// Gets the number of elements contained in the map.
+        /// </summary>
         public int Count { get { return list.Count; } }
+
+        /// <summary>
+        /// Gets a value indicating whether the map is read-only.
+        /// </summary>
         public bool IsReadOnly { get { return false; } }
 
+        /// <summary>
+        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
+        /// </summary>
+        /// <param name="other">The <see cref="System.Object" /> to compare with this instance.</param>
+        /// <returns>
+        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
+        /// </returns>
         public override bool Equals(object other)
         {
             return Equals(other as MapField<TKey, TValue>);
         }
 
+        /// <summary>
+        /// Returns a hash code for this instance.
+        /// </summary>
+        /// <returns>
+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
+        /// </returns>
         public override int GetHashCode()
         {
             var valueComparer = EqualityComparer<TValue>.Default;
@@ -271,6 +378,14 @@ namespace Google.Protobuf.Collections
             return hash;
         }
 
+        /// <summary>
+        /// Compares this map with another for equality.
+        /// </summary>
+        /// <remarks>
+        /// The order of the key/value pairs in the maps is not deemed significant in this comparison.
+        /// </remarks>
+        /// <param name="other">The map to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal map; <c>false</c> otherwise.</returns>
         public bool Equals(MapField<TKey, TValue> other)
         {
             if (other == null)
@@ -322,6 +437,12 @@ namespace Google.Protobuf.Collections
             } while (input.MaybeConsumeTag(codec.MapTag));
         }
 
+        /// <summary>
+        /// Writes the contents of this map to the given coded output stream, using the specified codec
+        /// to encode each entry.
+        /// </summary>
+        /// <param name="output">The output stream to write to.</param>
+        /// <param name="codec">The codec to use for each entry.</param>
         public void WriteTo(CodedOutputStream output, Codec codec)
         {
             var message = new Codec.MessageAdapter(codec);
@@ -334,6 +455,11 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Calculates the size of this map based on the given entry codec.
+        /// </summary>
+        /// <param name="codec">The codec to use to encode each entry.</param>
+        /// <returns></returns>
         public int CalculateSize(Codec codec)
         {
             if (Count == 0)
@@ -446,7 +572,7 @@ namespace Google.Protobuf.Collections
         }
 
         /// <summary>
-        /// A codec for a specific map field. This contains all the information required to encoded and
+        /// A codec for a specific map field. This contains all the information required to encode and
         /// decode the nested messages.
         /// </summary>
         public sealed class Codec
@@ -455,6 +581,13 @@ namespace Google.Protobuf.Collections
             private readonly FieldCodec<TValue> valueCodec;
             private readonly uint mapTag;
 
+            /// <summary>
+            /// Creates a new entry codec based on a separate key codec and value codec,
+            /// and the tag to use for each map entry.
+            /// </summary>
+            /// <param name="keyCodec">The key codec.</param>
+            /// <param name="valueCodec">The value codec.</param>
+            /// <param name="mapTag">The map tag to use to introduce each map entry.</param>
             public Codec(FieldCodec<TKey> keyCodec, FieldCodec<TValue> valueCodec, uint mapTag)
             {
                 this.keyCodec = keyCodec;

+ 109 - 2
csharp/src/Google.Protobuf/Collections/RepeatedField.cs

@@ -30,7 +30,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using Google.Protobuf.Reflection;
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -81,6 +80,11 @@ namespace Google.Protobuf.Collections
             return clone;
         }
 
+        /// <summary>
+        /// Adds the entries from the given input stream, decoding them with the specified codec.
+        /// </summary>
+        /// <param name="input">The input stream to read from.</param>
+        /// <param name="codec">The codec to use in order to read each entry.</param>
         public void AddEntriesFrom(CodedInputStream input, FieldCodec<T> codec)
         {
             // TODO: Inline some of the Add code, so we can avoid checking the size on every
@@ -112,6 +116,12 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Calculates the size of this collection based on the given codec.
+        /// </summary>
+        /// <param name="codec">The codec to use when encoding each field.</param>
+        /// <returns>The number of bytes that would be written to a <see cref="CodedOutputStream"/> by <see cref="WriteTo"/>,
+        /// using the same codec.</returns>
         public int CalculateSize(FieldCodec<T> codec)
         {
             if (count == 0)
@@ -157,6 +167,12 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Writes the contents of this collection to the given <see cref="CodedOutputStream"/>,
+        /// encoding each value using the specified codec.
+        /// </summary>
+        /// <param name="output">The output stream to write to.</param>
+        /// <param name="codec">The codec to use when encoding each value.</param>
         public void WriteTo(CodedOutputStream output, FieldCodec<T> codec)
         {
             if (count == 0)
@@ -200,6 +216,10 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Adds the specified item to the collection.
+        /// </summary>
+        /// <param name="item">The item to add.</param>
         public void Add(T item)
         {
             if (item == null)
@@ -210,22 +230,40 @@ namespace Google.Protobuf.Collections
             array[count++] = item;
         }
 
+        /// <summary>
+        /// Removes all items from the collection.
+        /// </summary>
         public void Clear()
         {
             array = EmptyArray;
             count = 0;
         }
 
+        /// <summary>
+        /// Determines whether this collection contains the given item.
+        /// </summary>
+        /// <param name="item">The item to find.</param>
+        /// <returns><c>true</c> if this collection contains the given item; <c>false</c> otherwise.</returns>
         public bool Contains(T item)
         {
             return IndexOf(item) != -1;
         }
 
+        /// <summary>
+        /// Copies this collection to the given array.
+        /// </summary>
+        /// <param name="array">The array to copy to.</param>
+        /// <param name="arrayIndex">The first index of the array to copy to.</param>
         public void CopyTo(T[] array, int arrayIndex)
         {
             Array.Copy(this.array, 0, array, arrayIndex, count);
         }
 
+        /// <summary>
+        /// Removes the specified item from the collection
+        /// </summary>
+        /// <param name="item">The item to remove.</param>
+        /// <returns><c>true</c> if the item was found and removed; <c>false</c> otherwise.</returns>
         public bool Remove(T item)
         {
             int index = IndexOf(item);
@@ -239,10 +277,22 @@ namespace Google.Protobuf.Collections
             return true;
         }
 
+        /// <summary>
+        /// Gets the number of elements contained in the collection.
+        /// </summary>
         public int Count { get { return count; } }
 
+        /// <summary>
+        /// Gets a value indicating whether the collection is read-only.
+        /// </summary>
         public bool IsReadOnly { get { return false; } }
 
+        // TODO: Remove this overload and just handle it in the one below, at execution time?
+
+        /// <summary>
+        /// Adds all of the specified values into this collection.
+        /// </summary>
+        /// <param name="values">The values to add to this collection.</param>
         public void Add(RepeatedField<T> values)
         {
             if (values == null)
@@ -255,6 +305,10 @@ namespace Google.Protobuf.Collections
             count += values.count;
         }
 
+        /// <summary>
+        /// Adds all of the specified values into this collection.
+        /// </summary>
+        /// <param name="values">The values to add to this collection.</param>
         public void Add(IEnumerable<T> values)
         {
             if (values == null)
@@ -268,6 +322,12 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Returns an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>
+        /// An enumerator that can be used to iterate through the collection.
+        /// </returns>
         public IEnumerator<T> GetEnumerator()
         {
             for (int i = 0; i < count; i++)
@@ -276,16 +336,35 @@ namespace Google.Protobuf.Collections
             }
         }
 
+        /// <summary>
+        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
+        /// </summary>
+        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
+        /// <returns>
+        ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
+        /// </returns>
         public override bool Equals(object obj)
         {
             return Equals(obj as RepeatedField<T>);
         }
 
+        /// <summary>
+        /// Returns an enumerator that iterates through a collection.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
+        /// </returns>
         IEnumerator IEnumerable.GetEnumerator()
         {
             return GetEnumerator();
-        }        
+        }
 
+        /// <summary>
+        /// Returns a hash code for this instance.
+        /// </summary>
+        /// <returns>
+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
+        /// </returns>
         public override int GetHashCode()
         {
             int hash = 0;
@@ -296,6 +375,11 @@ namespace Google.Protobuf.Collections
             return hash;
         }
 
+        /// <summary>
+        /// Compares this repeated field with another for equality.
+        /// </summary>
+        /// <param name="other">The repeated field to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal repeated field; <c>false</c> otherwise.</returns>
         public bool Equals(RepeatedField<T> other)
         {
             if (ReferenceEquals(other, null))
@@ -322,6 +406,12 @@ namespace Google.Protobuf.Collections
             return true;
         }
 
+        /// <summary>
+        /// Returns the index of the given item within the collection, or -1 if the item is not
+        /// present.
+        /// </summary>
+        /// <param name="item">The item to find in the collection.</param>
+        /// <returns>The zero-based index of the item, or -1 if it is not found.</returns>
         public int IndexOf(T item)
         {
             if (item == null)
@@ -340,6 +430,11 @@ namespace Google.Protobuf.Collections
             return -1;
         }
 
+        /// <summary>
+        /// Inserts the given item at the specified index.
+        /// </summary>
+        /// <param name="index">The index at which to insert the item.</param>
+        /// <param name="item">The item to insert.</param>
         public void Insert(int index, T item)
         {
             if (item == null)
@@ -356,6 +451,10 @@ namespace Google.Protobuf.Collections
             count++;
         }
 
+        /// <summary>
+        /// Removes the item at the given index.
+        /// </summary>
+        /// <param name="index">The zero-based index of the item to remove.</param>
         public void RemoveAt(int index)
         {
             if (index < 0 || index >= count)
@@ -367,6 +466,14 @@ namespace Google.Protobuf.Collections
             array[count] = default(T);
         }
 
+        /// <summary>
+        /// Gets or sets the item at the specified index.
+        /// </summary>
+        /// <value>
+        /// The element at the specified index.
+        /// </value>
+        /// <param name="index">The zero-based index of the element to get or set.</param>
+        /// <returns>The item at the specified index.</returns>
         public T this[int index]
         {
             get

+ 107 - 0
csharp/src/Google.Protobuf/FieldCodec.cs

@@ -41,76 +41,152 @@ namespace Google.Protobuf
     public static class FieldCodec
     {
         // TODO: Avoid the "dual hit" of lambda expressions: create open delegates instead. (At least test...)
+
+        /// <summary>
+        /// Retrieves a codec suitable for a string field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<string> ForString(uint tag)
         {
             return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a bytes field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<ByteString> ForBytes(uint tag)
         {
             return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a bool field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<bool> ForBool(uint tag)
         {
             return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for an int32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<int> ForInt32(uint tag)
         {
             return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for an sint32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<int> ForSInt32(uint tag)
         {
             return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a fixed32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<uint> ForFixed32(uint tag)
         {
             return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for an sfixed32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<int> ForSFixed32(uint tag)
         {
             return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a uint32 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<uint> ForUInt32(uint tag)
         {
             return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for an int64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<long> ForInt64(uint tag)
         {
             return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for an sint64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<long> ForSInt64(uint tag)
         {
             return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a fixed64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<ulong> ForFixed64(uint tag)
         {
             return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for an sfixed64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<long> ForSFixed64(uint tag)
         {
             return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a uint64 field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<ulong> ForUInt64(uint tag)
         {
             return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a float field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<float> ForFloat(uint tag)
         {
             return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a double field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<double> ForDouble(uint tag)
         {
             return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag);
@@ -118,6 +194,14 @@ namespace Google.Protobuf
 
         // Enums are tricky. We can probably use expression trees to build these delegates automatically,
         // but it's easy to generate the code for it.
+
+        /// <summary>
+        /// Retrieves a codec suitable for an enum field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <param name="toInt32">A conversion function from <see cref="Int32"/> to the enum type.</param>
+        /// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
         {
             return new FieldCodec<T>(input => fromInt32(
@@ -126,6 +210,12 @@ namespace Google.Protobuf
                 value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag);
         }
 
+        /// <summary>
+        /// Retrieves a codec suitable for a message field with the given tag.
+        /// </summary>
+        /// <param name="tag">The tag.</param>
+        /// <param name="parser">A parser to use for the message type.</param>
+        /// <returns>A codec for the given tag.</returns>
         public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : IMessage<T>
         {
             return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; },
@@ -344,8 +434,20 @@ namespace Google.Protobuf
         /// </summary>
         internal int FixedSize { get { return fixedSize; } }
 
+        /// <summary>
+        /// Gets the tag of the codec.
+        /// </summary>
+        /// <value>
+        /// The tag of the codec.
+        /// </value>
         public uint Tag { get { return tag; } }
 
+        /// <summary>
+        /// Gets the default value of the codec's type.
+        /// </summary>
+        /// <value>
+        /// The default value of the codec's type.
+        /// </value>
         public T DefaultValue { get { return defaultValue; } }
 
         /// <summary>
@@ -360,6 +462,11 @@ namespace Google.Protobuf
             }
         }
 
+        /// <summary>
+        /// Reads a value of the codec type from the given <see cref="CodedInputStream"/>.
+        /// </summary>
+        /// <param name="input">The input stream to read from.</param>
+        /// <returns>The value read from the stream.</returns>
         public T Read(CodedInputStream input)
         {
             return reader(input);

+ 9 - 3
csharp/src/Google.Protobuf/Google.Protobuf.csproj

@@ -24,12 +24,14 @@
     <OutputPath>bin\Debug</OutputPath>
     <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
     <DocumentationFile>bin\Debug\Google.Protobuf.xml</DocumentationFile>
-    <NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
+    <NoWarn>
+    </NoWarn>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <NoStdLib>true</NoStdLib>
     <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -37,12 +39,14 @@
     <OutputPath>bin\Release</OutputPath>
     <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
     <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
-    <NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
+    <NoWarn>
+    </NoWarn>
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <NoStdLib>true</NoStdLib>
     <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -50,7 +54,8 @@
     <OutputPath>bin\ReleaseSigned</OutputPath>
     <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
     <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
-    <NoWarn>1591, 1570, 1571, 1572, 1573, 1574</NoWarn>
+    <NoWarn>
+    </NoWarn>
     <DefineConstants>TRACE;SIGNED</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
@@ -58,6 +63,7 @@
     <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
     <SignAssembly>True</SignAssembly>
     <AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="mscorlib" />

+ 2 - 1
csharp/src/Google.Protobuf/IMessage.cs

@@ -91,8 +91,9 @@ namespace Google.Protobuf
 
     /// <summary>
     /// Generic interface for a deeply cloneable type.
-    /// <summary>
+    /// </summary>
     /// <remarks>
+    /// <para>
     /// All generated messages implement this interface, but so do some non-message types.
     /// Additionally, due to the type constraint on <c>T</c> in <see cref="IMessage{T}"/>,
     /// it is simpler to keep this as a separate interface.

+ 5 - 2
csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs

@@ -45,7 +45,7 @@ namespace Google.Protobuf
         {
         }
 
-        public static InvalidProtocolBufferException TruncatedMessage()
+        internal static InvalidProtocolBufferException TruncatedMessage()
         {
             return new InvalidProtocolBufferException(
                 "While parsing a protocol message, the input ended unexpectedly " +
@@ -61,12 +61,15 @@ namespace Google.Protobuf
                 "which claimed to have negative size.");
         }
 
-        public static InvalidProtocolBufferException MalformedVarint()
+        internal static InvalidProtocolBufferException MalformedVarint()
         {
             return new InvalidProtocolBufferException(
                 "CodedInputStream encountered a malformed varint.");
         }
 
+        /// <summary>
+        /// Creates an exception for an error condition of an invalid tag being encountered.
+        /// </summary>
         public static InvalidProtocolBufferException InvalidTag()
         {
             return new InvalidProtocolBufferException(

+ 13 - 0
csharp/src/Google.Protobuf/JsonFormatter.cs

@@ -114,11 +114,20 @@ namespace Google.Protobuf
 
         private readonly Settings settings;
 
+        /// <summary>
+        /// Creates a new formatted with the given settings.
+        /// </summary>
+        /// <param name="settings">The settings.</param>
         public JsonFormatter(Settings settings)
         {
             this.settings = settings;
         }
 
+        /// <summary>
+        /// Formats the specified message as JSON.
+        /// </summary>
+        /// <param name="message">The message to format.</param>
+        /// <returns>The formatted message.</returns>
         public string Format(IMessage message)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -767,6 +776,10 @@ namespace Google.Protobuf
             /// </summary>
             public bool FormatDefaultValues { get { return formatDefaultValues; } }
 
+            /// <summary>
+            /// Creates a new <see cref="Settings"/> object with the specified formatting of default values.
+            /// </summary>
+            /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param>
             public Settings(bool formatDefaultValues)
             {
                 this.formatDefaultValues = formatDefaultValues;

+ 44 - 0
csharp/src/Google.Protobuf/MessageExtensions.cs

@@ -39,6 +39,11 @@ namespace Google.Protobuf
     /// </summary>
     public static class MessageExtensions
     {
+        /// <summary>
+        /// Merges data from the given byte array into an existing message.
+        /// </summary>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param>
         public static void MergeFrom(this IMessage message, byte[] data)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -48,6 +53,11 @@ namespace Google.Protobuf
             input.CheckLastTagWas(0);
         }
 
+        /// <summary>
+        /// Merges data from the given byte string into an existing message.
+        /// </summary>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param>
         public static void MergeFrom(this IMessage message, ByteString data)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -57,6 +67,11 @@ namespace Google.Protobuf
             input.CheckLastTagWas(0);
         }
 
+        /// <summary>
+        /// Merges data from the given stream into an existing message.
+        /// </summary>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param>
         public static void MergeFrom(this IMessage message, Stream input)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -66,6 +81,15 @@ namespace Google.Protobuf
             codedInput.CheckLastTagWas(0);
         }
 
+        /// <summary>
+        /// Merges length-delimited data from the given stream into an existing message.
+        /// </summary>
+        /// <remarks>
+        /// The stream is expected to contain a length and then the data. Only the amount of data
+        /// specified by the length will be consumed.
+        /// </remarks>
+        /// <param name="message">The message to merge the data into.</param>
+        /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param>
         public static void MergeDelimitedFrom(this IMessage message, Stream input)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -75,6 +99,11 @@ namespace Google.Protobuf
             message.MergeFrom(limitedStream);
         }
 
+        /// <summary>
+        /// Converts the given message into a byte array in protobuf encoding.
+        /// </summary>
+        /// <param name="message">The message to convert.</param>
+        /// <returns>The message data as a byte array.</returns>
         public static byte[] ToByteArray(this IMessage message)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -85,6 +114,11 @@ namespace Google.Protobuf
             return result;
         }
 
+        /// <summary>
+        /// Writes the given message data to the given stream in protobuf encoding.
+        /// </summary>
+        /// <param name="message">The message to write to the stream.</param>
+        /// <param name="output">The stream to write to.</param>
         public static void WriteTo(this IMessage message, Stream output)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -94,6 +128,11 @@ namespace Google.Protobuf
             codedOutput.Flush();
         }
 
+        /// <summary>
+        /// Writes the length and then data of the given message to a stream.
+        /// </summary>
+        /// <param name="message">The message to write.</param>
+        /// <param name="output">The output stream to write to.</param>
         public static void WriteDelimitedTo(this IMessage message, Stream output)
         {
             Preconditions.CheckNotNull(message, "message");
@@ -104,6 +143,11 @@ namespace Google.Protobuf
             codedOutput.Flush();
         }
 
+        /// <summary>
+        /// Converts the given message into a byte string in protobuf encoding.
+        /// </summary>
+        /// <param name="message">The message to convert.</param>
+        /// <returns>The message data as a byte string.</returns>
         public static ByteString ToByteString(this IMessage message)
         {
             Preconditions.CheckNotNull(message, "message");

+ 24 - 0
csharp/src/Google.Protobuf/MessageParser.cs

@@ -90,6 +90,11 @@ namespace Google.Protobuf
             return message;
         }
 
+        /// <summary>
+        /// Parses a message from the given byte string.
+        /// </summary>
+        /// <param name="data">The data to parse.</param>
+        /// <returns>The parsed message.</returns>
         public T ParseFrom(ByteString data)
         {
             Preconditions.CheckNotNull(data, "data");
@@ -98,6 +103,11 @@ namespace Google.Protobuf
             return message;
         }
 
+        /// <summary>
+        /// Parses a message from the given stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
         public T ParseFrom(Stream input)
         {
             T message = factory();
@@ -105,6 +115,15 @@ namespace Google.Protobuf
             return message;
         }
 
+        /// <summary>
+        /// Parses a length-delimited message from the given stream.
+        /// </summary>
+        /// <remarks>
+        /// The stream is expected to contain a length and then the data. Only the amount of data
+        /// specified by the length will be consumed.
+        /// </remarks>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
         public T ParseDelimitedFrom(Stream input)
         {
             T message = factory();
@@ -112,6 +131,11 @@ namespace Google.Protobuf
             return message;
         }
 
+        /// <summary>
+        /// Parses a message from the given coded input stream.
+        /// </summary>
+        /// <param name="input">The stream to parse.</param>
+        /// <returns>The parsed message.</returns>
         public T ParseFrom(CodedInputStream input)
         {
             T message = factory();

+ 1 - 1
csharp/src/Google.Protobuf/Preconditions.cs

@@ -57,7 +57,7 @@ namespace Google.Protobuf
         /// return the value to the caller.
         /// </summary>
         /// <remarks>
-        /// This is equivalent to <see cref="CheckNotNull"/> but without the type parameter
+        /// This is equivalent to <see cref="CheckNotNull{T}(T, string)"/> but without the type parameter
         /// constraint. In most cases, the constraint is useful to prevent you from calling CheckNotNull
         /// with a value type - but it gets in the way if either you want to use it with a nullable
         /// value type, or you want to use it with an unconstrained type parameter.

+ 3 - 0
csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs

@@ -61,6 +61,9 @@ namespace Google.Protobuf.Reflection
             get { return index; }
         }
 
+        /// <summary>
+        /// Returns the name of the entity (field, message etc) being described.
+        /// </summary>
         public abstract string Name { get; }
 
         /// <summary>

+ 10 - 1
csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs

@@ -51,11 +51,20 @@ namespace Google.Protobuf.Reflection
         }
 
         internal EnumValueDescriptorProto Proto { get { return proto; } }
-        
+
+        /// <summary>
+        /// Returns the name of the enum value described by this object.
+        /// </summary>
         public override string Name { get { return proto.Name; } }
 
+        /// <summary>
+        /// Returns the number associated with this enum value.
+        /// </summary>
         public int Number { get { return Proto.Number; } }
 
+        /// <summary>
+        /// Returns the enum descriptor that this value is part of.
+        /// </summary>
         public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } }
     }
 }

+ 32 - 5
csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs

@@ -93,6 +93,15 @@ namespace Google.Protobuf.Reflection
 
         internal FieldDescriptorProto Proto { get { return proto; } }
 
+        /// <summary>
+        /// Returns the accessor for this field, or <c>null</c> if this descriptor does
+        /// not support reflective access.
+        /// </summary>
+        /// <remarks>
+        /// While a <see cref="FieldDescriptor"/> describes the field, it does not provide
+        /// any way of obtaining or changing the value of the field within a specific message;
+        /// that is the responsibility of the accessor.
+        /// </remarks>
         public IFieldAccessor Accessor { get { return accessor; } }
         
         /// <summary>
@@ -141,43 +150,61 @@ namespace Google.Protobuf.Reflection
                 default:
                     throw new ArgumentException("Invalid type specified");
             }
-        }        
+        }
 
+        /// <summary>
+        /// Returns <c>true</c> if this field is a repeated field; <c>false</c> otherwise.
+        /// </summary>
         public bool IsRepeated
         {
             get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; }
         }
 
+        /// <summary>
+        /// Returns <c>true</c> if this field is a map field; <c>false</c> otherwise.
+        /// </summary>
         public bool IsMap
         {
             get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; }
         }
 
+        // TODO(jonskeet): Check whether this is correct with proto3, where we default to packed...
+
+        /// <summary>
+        /// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
+        /// </summary>
         public bool IsPacked
         {
             get { return Proto.Options != null && Proto.Options.Packed; }
         }        
 
         /// <summary>
-        /// Get the field's containing type. For extensions, this is the type being
-        /// extended, not the location where the extension was defined. See
-        /// <see cref="ExtensionScope" />.
+        /// Get the field's containing message type.
         /// </summary>
         public MessageDescriptor ContainingType
         {
             get { return containingType; }
         }
 
+        /// <summary>
+        /// Returns the oneof containing this field, or <c>null</c> if it is not part of a oneof.
+        /// </summary>
         public OneofDescriptor ContainingOneof
         {
             get { return containingOneof; }
-        }        
+        }
 
+        /// <summary>
+        /// Returns  the type of the field.
+        /// </summary>
         public FieldType FieldType
         {
             get { return fieldType; }
         }
 
+        /// <summary>
+        /// Returns the field number declared in the proto file.
+        /// </summary>
         public int FieldNumber
         {
             get { return Proto.Number; }

+ 55 - 2
csharp/src/Google.Protobuf/Reflection/FieldType.cs

@@ -33,28 +33,81 @@
 namespace Google.Protobuf.Reflection
 {
     /// <summary>
-    /// Enumeration of all the possible field types. The odd formatting is to make it very clear
-    /// which attribute applies to which value, while maintaining a compact format.
+    /// Enumeration of all the possible field types.
     /// </summary>
     public enum FieldType
     {
+        /// <summary>
+        /// The <c>double</c> field type.
+        /// </summary>
         Double,
+        /// <summary>
+        /// The <c>float</c> field type.
+        /// </summary>
         Float,
+        /// <summary>
+        /// The <c>int64</c> field type.
+        /// </summary>
         Int64,
+        /// <summary>
+        /// The <c>uint64</c> field type.
+        /// </summary>
         UInt64,
+        /// <summary>
+        /// The <c>int32</c> field type.
+        /// </summary>
         Int32,
+        /// <summary>
+        /// The <c>fixed64</c> field type.
+        /// </summary>
         Fixed64,
+        /// <summary>
+        /// The <c>fixed32</c> field type.
+        /// </summary>
         Fixed32,
+        /// <summary>
+        /// The <c>bool</c> field type.
+        /// </summary>
         Bool,
+        /// <summary>
+        /// The <c>string</c> field type.
+        /// </summary>
         String,
+        /// <summary>
+        /// The field type used for groups (not supported in this implementation).
+        /// </summary>
         Group,
+        /// <summary>
+        /// The field type used for message fields.
+        /// </summary>
         Message,
+        /// <summary>
+        /// The <c>bytes</c> field type.
+        /// </summary>
         Bytes,
+        /// <summary>
+        /// The <c>uint32</c> field type.
+        /// </summary>
         UInt32,
+        /// <summary>
+        /// The <c>sfixed32</c> field type.
+        /// </summary>
         SFixed32,
+        /// <summary>
+        /// The <c>sfixed64</c> field type.
+        /// </summary>
         SFixed64,
+        /// <summary>
+        /// The <c>sint32</c> field type.
+        /// </summary>
         SInt32,
+        /// <summary>
+        /// The <c>sint64</c> field type.
+        /// </summary>
         SInt64,
+        /// <summary>
+        /// The field type used for enum fields.
+        /// </summary>
         Enum
     }
 }

+ 8 - 13
csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs

@@ -51,18 +51,7 @@ namespace Google.Protobuf.Reflection
         private readonly IList<FileDescriptor> dependencies;
         private readonly IList<FileDescriptor> publicDependencies;
         private readonly DescriptorPool pool;
-
-        public enum ProtoSyntax
-        {
-            Proto2,
-            Proto3
-        }
-
-        public ProtoSyntax Syntax
-        {
-            get { return proto.Syntax == "proto3" ? ProtoSyntax.Proto3 : ProtoSyntax.Proto2; }
-        }
-
+        
         private FileDescriptor(ByteString descriptorData, FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies, GeneratedCodeInfo generatedCodeInfo)
         {
             this.descriptorData = descriptorData;
@@ -368,7 +357,13 @@ namespace Google.Protobuf.Reflection
                 throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e);
             }
         }
-        
+
+        /// <summary>
+        /// Returns a <see cref="System.String" /> that represents this instance.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="System.String" /> that represents this instance.
+        /// </returns>
         public override string ToString()
         {
             return "FileDescriptor for " + proto.Name;

+ 11 - 0
csharp/src/Google.Protobuf/Reflection/IDescriptor.cs

@@ -37,8 +37,19 @@ namespace Google.Protobuf.Reflection
     /// </summary>
     public interface IDescriptor
     {
+        /// <summary>
+        /// Returns the name of the entity (message, field etc) being described.
+        /// </summary>
         string Name { get; }
+
+        /// <summary>
+        /// Returns the fully-qualified name of the entity being described.
+        /// </summary>
         string FullName { get; }
+
+        /// <summary>
+        /// Returns the descriptor for the .proto file that this entity is part of.
+        /// </summary>
         FileDescriptor File { get; }
     }    
 }

+ 4 - 1
csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs

@@ -30,6 +30,9 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
+using System;
+using System.Collections;
+
 namespace Google.Protobuf.Reflection
 {
     /// <summary>
@@ -64,7 +67,7 @@ namespace Google.Protobuf.Reflection
         /// Repeated fields are mutated by fetching the value and manipulating it as a list.
         /// Map fields are mutated by fetching the value and manipulating it as a dictionary.
         /// </remarks>
-        /// <exception cref="InvalidOperationException">The field is not a "simple" field, or the message is frozen.</exception>
+        /// <exception cref="InvalidOperationException">The field is not a "simple" field.</exception>
         void SetValue(object message, object value);
     }
 }

+ 4 - 2
csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs

@@ -30,7 +30,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using Google.Protobuf.Collections;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -163,6 +162,9 @@ namespace Google.Protobuf.Reflection
             get { return enumTypes; }
         }
 
+        /// <value>
+        /// An unmodifiable list of the "oneof" field collections in this message type.
+        /// </value>
         public IList<OneofDescriptor> Oneofs
         {
             get { return oneofs; }
@@ -276,7 +278,7 @@ namespace Google.Protobuf.Reflection
             /// <summary>
             /// Retrieves the descriptor for the field with the given name.
             /// </summary>
-            /// <param name="number">Number of the field to retrieve the descriptor for</param>
+            /// <param name="name">Name of the field to retrieve the descriptor for</param>
             /// <returns>The descriptor for the given field</returns>
             /// <exception cref="KeyNotFoundException">The message descriptor does not contain a field
             /// with the given name</exception>

+ 6 - 0
csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs

@@ -58,6 +58,12 @@ namespace Google.Protobuf.Reflection
             clearDelegate = ReflectionUtil.CreateActionObject(clearMethod);
         }
 
+        /// <summary>
+        /// Gets the descriptor for this oneof.
+        /// </summary>
+        /// <value>
+        /// The descriptor of the oneof.
+        /// </value>
         public OneofDescriptor Descriptor { get { return descriptor; } }
 
         /// <summary>

+ 24 - 1
csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs

@@ -32,11 +32,14 @@
 
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
-using System.Linq;
 using Google.Protobuf.Compatibility;
 
 namespace Google.Protobuf.Reflection
 {
+    /// <summary>
+    /// Describes a "oneof" field collection in a message type: a set of
+    /// fields of which at most one can be set in any particular message.
+    /// </summary>
     public sealed class OneofDescriptor : DescriptorBase
     {
         private readonly OneofDescriptorProto proto;
@@ -59,13 +62,33 @@ namespace Google.Protobuf.Reflection
         /// </summary>
         public override string Name { get { return proto.Name; } }
 
+        /// <summary>
+        /// Gets the message type containing this oneof.
+        /// </summary>
+        /// <value>
+        /// The message type containing this oneof.
+        /// </value>
         public MessageDescriptor ContainingType
         {
             get { return containingType; }
         }
 
+        /// <summary>
+        /// Gets the fields within this oneof, in declaration order.
+        /// </summary>
+        /// <value>
+        /// The fields within this oneof, in declaration order.
+        /// </value>
         public IList<FieldDescriptor> Fields { get { return fields; } }
 
+        /// <summary>
+        /// Gets an accessor for reflective access to the values associated with the oneof
+        /// in a particular message.
+        /// </summary>
+        /// <value>
+        /// The accessor used for reflective access, or <c>null</c> if reflection is not
+        /// supported by this descriptor.
+        /// </value>
         public OneofAccessor Accessor { get { return accessor; } }
 
         internal void CrossLink()

+ 6 - 0
csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs

@@ -38,7 +38,13 @@ namespace Google.Protobuf.WellKnownTypes
     // providing a conversion to TimeSpan and convenience operators.
     public partial class Duration
     {
+        /// <summary>
+        /// The number of nanoseconds in a second.
+        /// </summary>
         public const int NanosecondsPerSecond = 1000000000;
+        /// <summary>
+        /// The number of nanoseconds in a BCL tick (as used by <see cref="TimeSpan"/> and <see cref="DateTime"/>).
+        /// </summary>
         public const int NanosecondsPerTick = 100;
 
         /// <summary>

+ 19 - 0
csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs

@@ -43,16 +43,35 @@ namespace Google.Protobuf.WellKnownTypes
     /// </summary>
     public static class TimeExtensions
     {
+        /// <summary>
+        /// Converts the given <see cref="DateTime"/> to a <see cref="Timestamp"/>.
+        /// </summary>
+        /// <param name="dateTime">The date and time to convert to a timestamp.</param>
+        /// <exception cref="ArgumentException">The <paramref name="dateTime"/> value has a <see cref="DateTime.Kind"/>other than <c>Utc</c>.</exception>
+        /// <returns>The converted timestamp.</returns>
         public static Timestamp ToTimestamp(this DateTime dateTime)
         {
             return Timestamp.FromDateTime(dateTime);
         }
 
+        /// <summary>
+        /// Converts the given <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/>
+        /// </summary>
+        /// <remarks>The offset is taken into consideration when converting the value (so the same instant in time
+        /// is represented) but is not a separate part of the resulting value. In other words, there is no
+        /// roundtrip operation to retrieve the original <c>DateTimeOffset</c>.</remarks>
+        /// <param name="dateTimeOffset">The date and time (with UTC offset) to convert to a timestamp.</param>
+        /// <returns>The converted timestamp.</returns>
         public static Timestamp ToTimestamp(this DateTimeOffset dateTimeOffset)
         {
             return Timestamp.FromDateTimeOffset(dateTimeOffset);
         }
 
+        /// <summary>
+        /// Converts the given <see cref="TimeSpan"/> to a <see cref="Duration"/>.
+        /// </summary>
+        /// <param name="timeSpan">The time span to convert.</param>
+        /// <returns>The converted duration.</returns>
         public static Duration ToDuration(this TimeSpan timeSpan)
         {
             return Duration.FromTimeSpan(timeSpan);

+ 5 - 2
csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs

@@ -136,9 +136,12 @@ namespace Google.Protobuf.WellKnownTypes
         }
 
         /// <summary>
-        /// Converts the specified <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/>.
+        /// Converts the given <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/>
         /// </summary>
-        /// <param name="dateTime"></param>
+        /// <remarks>The offset is taken into consideration when converting the value (so the same instant in time
+        /// is represented) but is not a separate part of the resulting value. In other words, there is no
+        /// roundtrip operation to retrieve the original <c>DateTimeOffset</c>.</remarks>
+        /// <param name="dateTimeOffset">The date and time (with UTC offset) to convert to a timestamp.</param>
         /// <returns>The converted timestamp.</returns>
         public static Timestamp FromDateTimeOffset(DateTimeOffset dateTimeOffset)
         {

+ 27 - 62
csharp/src/Google.Protobuf/WireFormat.cs

@@ -30,9 +30,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using System;
-using Google.Protobuf.Reflection;
-
 namespace Google.Protobuf
 {
     /// <summary>
@@ -59,13 +56,34 @@ namespace Google.Protobuf
 
         #endregion
 
+        /// <summary>
+        /// Wire types within protobuf encoding.
+        /// </summary>
         public enum WireType : uint
         {
+            /// <summary>
+            /// Variable-length integer.
+            /// </summary>
             Varint = 0,
+            /// <summary>
+            /// A fixed-length 64-bit value.
+            /// </summary>
             Fixed64 = 1,
+            /// <summary>
+            /// A length-delimited value, i.e. a length followed by that many bytes of data.
+            /// </summary>
             LengthDelimited = 2,
+            /// <summary>
+            /// A "start group" value - not supported by this implementation.
+            /// </summary>
             StartGroup = 3,
+            /// <summary>
+            /// An "end group" value - not supported by this implementation.
+            /// </summary>
             EndGroup = 4,
+            /// <summary>
+            /// A fixed-length 32-bit value.
+            /// </summary>
             Fixed32 = 5
         }
         
@@ -80,6 +98,11 @@ namespace Google.Protobuf
             return (WireType) (tag & TagTypeMask);
         }
 
+        /// <summary>
+        /// Determines whether the given tag is an end group tag.
+        /// </summary>
+        /// <param name="tag">The tag to check.</param>
+        /// <returns><c>true</c> if the given tag is an end group tag; <c>false</c> otherwise.</returns>
         public static bool IsEndGroupTag(uint tag)
         {
             return (WireType) (tag & TagTypeMask) == WireType.EndGroup;
@@ -99,64 +122,6 @@ namespace Google.Protobuf
         public static uint MakeTag(int fieldNumber, WireType wireType)
         {
             return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
-        }
-
-        public static uint MakeTag(FieldDescriptor field)
-        {
-            return MakeTag(field.FieldNumber, GetWireType(field));
-        }
-
-        /// <summary>
-        /// Returns the wire type for the given field descriptor. This differs
-        /// from GetWireType(FieldType) for packed repeated fields.
-        /// </summary>
-        internal static WireType GetWireType(FieldDescriptor descriptor)
-        {
-            return descriptor.IsPacked ? WireType.LengthDelimited : GetWireType(descriptor.FieldType);
-        }
-
-        /// <summary>
-        /// Converts a field type to its wire type. Done with a switch for the sake
-        /// of speed - this is significantly faster than a dictionary lookup.
-        /// </summary>
-        public static WireType GetWireType(FieldType fieldType)
-        {
-            switch (fieldType)
-            {
-                case FieldType.Double:
-                    return WireType.Fixed64;
-                case FieldType.Float:
-                    return WireType.Fixed32;
-                case FieldType.Int64:
-                case FieldType.UInt64:
-                case FieldType.Int32:
-                    return WireType.Varint;
-                case FieldType.Fixed64:
-                    return WireType.Fixed64;
-                case FieldType.Fixed32:
-                    return WireType.Fixed32;
-                case FieldType.Bool:
-                    return WireType.Varint;
-                case FieldType.String:
-                    return WireType.LengthDelimited;
-                case FieldType.Group:
-                    return WireType.StartGroup;
-                case FieldType.Message:
-                case FieldType.Bytes:
-                    return WireType.LengthDelimited;
-                case FieldType.UInt32:
-                    return WireType.Varint;
-                case FieldType.SFixed32:
-                    return WireType.Fixed32;
-                case FieldType.SFixed64:
-                    return WireType.Fixed64;
-                case FieldType.SInt32:
-                case FieldType.SInt64:
-                case FieldType.Enum:
-                    return WireType.Varint;
-                default:
-                    throw new ArgumentOutOfRangeException("fieldType", "No such field type");
-            }
-        }
+        }        
     }
 }