Improve string encoding times.

Cache a reference to Encoding.UTF8 - the property access is (rather surprisingly) significant.
Additionally, when we detect that the string is all ASCII (due to the computed length in bytes being the length in characters), we can perform the encoding very efficiently ourselves.
diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs
index 5457f79..58475ff 100644
--- a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs
+++ b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs
@@ -135,7 +135,7 @@
         /// </summary>

         public static int ComputeStringSize(int fieldNumber, String value)

         {

-            int byteArraySize = Encoding.UTF8.GetByteCount(value);

+            int byteArraySize = UTF8.GetByteCount(value);

             return ComputeTagSize(fieldNumber) +

                    ComputeRawVarint32Size((uint) byteArraySize) +

                    byteArraySize;

@@ -323,7 +323,7 @@
         /// </summary>

         public static int ComputeStringSizeNoTag(String value)

         {

-            int byteArraySize = Encoding.UTF8.GetByteCount(value);

+            int byteArraySize = UTF8.GetByteCount(value);

             return ComputeRawVarint32Size((uint) byteArraySize) +

                    byteArraySize;

         }

diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.cs
index efc83d0..c817a20 100644
--- a/csharp/src/ProtocolBuffers/CodedOutputStream.cs
+++ b/csharp/src/ProtocolBuffers/CodedOutputStream.cs
@@ -58,6 +58,8 @@
     /// </remarks>

     public sealed partial class CodedOutputStream : ICodedOutputStream

     {

+        private static readonly Encoding UTF8 = Encoding.UTF8;

+

         /// <summary>

         /// The buffer size used by CreateInstance(Stream).

         /// </summary>

@@ -294,16 +296,26 @@
             WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);

             // Optimise the case where we have enough space to write

             // the string directly to the buffer, which should be common.

-            int length = Encoding.UTF8.GetByteCount(value);

+            int length = UTF8.GetByteCount(value);

             WriteRawVarint32((uint) length);

             if (limit - position >= length)

             {

-                Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);

+                if (length == value.Length) // Must be all ASCII...

+                {

+                                for (int i = 0; i < length; i++)

+                                {

+                        buffer[position + i] = (byte)value[i];

+                    }

+                }

+                else

+                {

+                    UTF8.GetBytes(value, 0, value.Length, buffer, position);

+                }

                 position += length;

             }

             else

             {

-                byte[] bytes = Encoding.UTF8.GetBytes(value);

+                byte[] bytes = UTF8.GetBytes(value);

                 WriteRawBytes(bytes);

             }

         }