C〓Protobufはどのようにして0をやり遂げてメモリの順序を割り当てますか?


タイトルは簡単ですが、IMessgeの対象がBytte[]にどうなりますか?
答え1:

msg.ToByteArray()
これはきっと私たちの要求に合わないです。
答え2:

using var memoryStream = new MemoryStream();
using var codedOutputStream = new CodedOutputStream(memoryStream);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();
memoryStream.ToArray();
この中にはmemoryStream、codedOutputStream、そしてToArayが一つの対象を作っています。また、MemoryStream内部にはもう一つのbyte[]オブジェクトが発生します。
要求に合わない
答え3:
MemoryStreamにbyte[]sliceを伝えて、MemoryStreamに直接byte[/]を使わせるという人がいます。

var bytes = new byte[msg.CalculateSize()];
using var memoryStream = new MemoryStream();
using var codedOutputStream = new CodedOutputStream(memoryStream);
msg.WriteTo(codedOutputStream);
codedOutputStream.Flush();
今回のニュースは直接的にBtesに整理されましたが、memoryStreamオブジェクト、codecOutputStream、そしてmemoryStream内部のbyte[]がまだあります。一つの対象を順番に並べましたが、三つのゴミの対象が生まれました。 
ですから、CodedOutputStream類をよく見てみましょう。

    /// <summary>
    /// Creates a new CodedOutputStream that writes directly to the given
    /// byte array. If more bytes are written than fit in the array,
    /// OutOfSpaceException will be thrown.
    /// </summary>
    public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length)
    {
    }

    /// <summary>
    /// Creates a new CodedOutputStream that writes directly to the given
    /// byte array slice. If more bytes are written than fit in the array,
    /// OutOfSpaceException will be thrown.
    /// </summary>
    private CodedOutputStream(byte[] buffer, int offset, int length)
    {
      this.output = null;
      this.buffer = buffer;
      this.position = offset;
      this.limit = offset + length;
      leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference
    }

byte[]のコンストラクタを提供しましたが、sliceのコンストラクタを提供していませんでした。幸いにも私有のコンストラクタがあります。
答え4:
ここではコードは書かれていません。プライベートコンストラクタを反射してCodedOutputStreamオブジェクトを構築することで、MemoryStreamと彼の内部のbyte[]を省きます。
今は答えに近いです。 
私たちの問題は、CodedOutputStreamも省けますか?
答え5来ました
よく観察してみると、このクラスはStreamを使用していない場合、バグ、limit、およびpositionのメンバー数だけを修正してもいいです。prvateメンバーですが、C〓〓は修正できます。
来たらすぐ実践しなさい

    delegate void ClearCodedOutputStream(CodedOutputStream stream, byte[] buffer, int offset, int count);
    static ClearCodedOutputStream ResetCodedOutputStream;
    static CodedOutputStream codedOutputStream = new CodedOutputStream(new byte[10]);

    static unsafe void Encode(IMessage msg, byte[] buffer)
    {
      ResetCodedOutputStream(codedOutputStream, buffer, 0, buffer.Length);
      msg.WriteTo(codedOutputStream);
      codedOutputStream.Flush();
    }

    static Action<T, TValue> MakeSetter<T, TValue>(FieldInfo field)
    {
      DynamicMethod m = new DynamicMethod(
        "setter", typeof(void), new Type[] { typeof(T), typeof(TValue) }, typeof(Program));
      ILGenerator cg = m.GetILGenerator();

      cg.Emit(OpCodes.Ldarg_0);
      cg.Emit(OpCodes.Ldarg_1);
      cg.Emit(OpCodes.Stfld, field);
      cg.Emit(OpCodes.Ret);

      return (Action<T, TValue>)m.CreateDelegate(typeof(Action<T, TValue>));
    }

    static void Main(string[] args)
    {
      var bufferField = typeof(CodedOutputStream).GetField("buffer", BindingFlags.NonPublic | BindingFlags.Instance);
      var limitField = typeof(CodedOutputStream).GetField("limit", BindingFlags.NonPublic | BindingFlags.Instance);
      var positionField = typeof(CodedOutputStream).GetField("position", BindingFlags.NonPublic | BindingFlags.Instance);

      var setLimit = MakeSetter<CodedOutputStream, int>(limitField);
      var setPosition = MakeSetter<CodedOutputStream, int>(positionField);
      var setBuffer = MakeSetter<CodedOutputStream, byte[]>(bufferField);

      ResetCodedOutputStream = (stream, buffer, offset, length) => 
      {
        //this.buffer = buffer;
        //this.position = offset;
        //this.limit = offset + length;
        setBuffer(stream, buffer);
        setPosition(stream, offset);
        setLimit(stream, offset + length);
      };

      var buffer = new byte[msg.CalculateSize()];
      Encode(msg, buffer);
    }
この実例コードの中で、staticのグローバルCodedOutputStreamを使って、本当に使う時、必ずスレッドの安全を保証します。
だから次の問題は:
1.CodedOutputStreamオブジェクトスレッドの安全を保証する方法
2.var buffer=new byte[msg.ClateSize];これも省きます
この二つの問題は読者に考えさせている。
Github:  http://github.com/egmkang
ここでは、C(ハ)Protobufをどうやって0メモリを割り当てるかについての序文を紹介します。C(ハ)Protobuf序列化の内容については、以前の文章を検索したり、下記の関連記事を引き続き閲覧したりしてください。これからもよろしくお願いします。