RingBuffer.cs

もどき。失敗点は以下の 2 つ。

  • Remove() と CopyTo() があまりに面倒で実装してないので ICollection<> からこれらを継承してる意味が無い。
    • ちまたの ring buffer の説明を見てみるとどちらもできなくても問題ないようなのでそもそも ICollection<> を実装する意味はないかも。
  • 末尾への要素追加しかできない。
    • これも ICollection<> の Add() を実装しているだけなので Perl でいうところの unshift は名前も含めてどうしようかという段階。

まぁ中身を参照することができる queue という感覚で作ったからこんな感じなんだけど。 deque を意識したら先頭に要素をつっこむことができるようにしてた、はず。

で、今回の出来に関わらずおれは多分 C# で ring buffer を書くことはこれ以降ない。というのも多分 C# だと unsafe keyword を併用して pointer をいじらないとうまいこと実装できなさそうなんだよな。組み込み型は値型 -> null を使うことができない -> Contains() や Remove() なんかを実装しにくいという理由から。 Generics の new() 制約をつけてしまう、というのは組み込み型使えなくなるから本末転倒だしな。

ちょっと調べてみたら C++ あたりで書いて DllImport するのが現実的ぽい。 C++/CLI を使うのはアレだしなぁ。

というわけで今回の sample 。

/*
 * Program.cs
 *  A sample for RingBuffer
 *
 * by janus_wel<janus.wel.3@gmail.com>
 * This source code is in public domain, and has NO WARRANTY.
 * */

using System.Diagnostics;
using Utility.Data;
using System;

namespace Sample
{
    class Program
    {
        static void Main(string[] args)
        {
            const int n = 8;
            RingBuffer<int> array = new RingBuffer<int>(n);

            Console.WriteLine("Filling circular array");
            for (int i = 0; i < n; ++i)
            {
                array.Add(i);
                Debug.Assert(array.Count == i + 1);
            }
            foreach (int i in array)
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Add one item");
            array.Add(10);
            Debug.Assert(array.Count == n);
            foreach (int i in array)
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Clear");
            array.Clear();
            Debug.Assert(array.Count == 0);

            foreach (int i in array)
            {
                Console.WriteLine(i);
            }
        }
    }
}