Back to Top

プログラムの覚書

C# IComparableインターフェイスの実装

C#にてIComparable, IComparable<T> インターフェースの実装について説明します。

IComparable<T>はIComparableのジェネリックです。

配列(Array)などのコンテナークラスでは数値等を格納した場合はソート等ができます。

IComparable、IComparable<T>を継承すれば、自作のクラスでもこれらの機能が使えます。

IComparableインターフェイスには、CompareToメソッドしかありません。のでこれを実装します。

IComparableの実装

 class Person : IComparable, IComparable<Person>
{
    //コンストラクタ
    public Person(string personName)
    {
        this._name = personName;
    }

    public string Name
    {
        get
        {
            return this._name;
        }
    }
    private string _name;

    public int CompareTo(object other)
    {
        return  _name.CompareTo(((Person)other).Name);
    }

    public int CompareTo(Person other)
    {
        return _name.CompareTo(other.Name);
    }
}

上の実装で

CompareTo(object other)がIComparableに

CompareTo(Person other)が IComparable<Person>に相当します。

またArrayListのSortはCompareTo(object other)を使用して並び替えます。

呼び出し側

private void button2_Click(object sender, EventArgs e)
{
    System.Collections.ArrayList al = new System.Collections.ArrayList();
    al.Add(new Person("もも"));
    al.Add(new Person("リンゴ"));
    al.Add(new Person("ナシ"));

    al.Sort();
}

 

Posted in C# | Leave a reply

C# 構造体とバイト配列(byte[])の変換

C#にて構造体(struct)からバイト配列(byte[])に内容のコピーをしたい時があります。

構造体とバイト配列のメモリーコピー方法は幾つかあり、またコピー速度も異なります。そのコピー方法を説明します。

サンプル構造体

unsafe struct Person 
{
    public fixed byte name[10];
    public fixed byte Age[5];
}

上記の構造体をもとに以下説明をします。

 

バイト配列(byte[])を構造体(struct)に変換する

構造体のサイズだけbyte配列を確保します。

Person pos = new Person();
int size = Marshal.SizeOf(pos);

byte[] buffer = new byte[size];

//bufferにデータコピー

 

Marshalを使用して構造体にコピーする

IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(buffer, 0, ptr, size);
pos = (Person)Marshal.PtrToStructure(ptr, typeof(Person));
Marshal.FreeHGlobal(ptr);

 

GCHandleを使用して構造体にコピーする

GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
pos = (Person)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(Person));
gch.Free();

 

ポインタで直接構造体にコピーする

unsafe
{
    fixed (byte* pbytes = buffer)
    {
        pos = *(Person*)pbytes;
    }
}

 

構造体(struct)をバイト配列(byte[])に変換する

Marshalを使用してバイト配列にコピーする

int size = Marshal.SizeOf(pos);

byte[] bytes = new byte[size];

//アンマネージメモリからメモリを割り当て
IntPtr ptr = Marshal.AllocHGlobal(size);

//マネージオブジェクトからアンマネージメモリにデータをマーシャリング
Marshal.StructureToPtr(pos, ptr, false);

//アンマネージデータをマネージのbyte[]にコピーする
Marshal.Copy(ptr, bytes, 0, size);

Marshal.FreeHGlobal(ptr);

 

GCHandleを使用してバイト配列にコピーする

int size = Marshal.SizeOf(pos);

byte[] bytes = new byte[size];

GCHandle gchw = GCHandle.Alloc(bytes, GCHandleType.Pinned);
Marshal.StructureToPtr(pos, gchw.AddrOfPinnedObject(), false);
gchw.Free();

 

ポインタで直接バイト配列にコピーする

int size = Marshal.SizeOf(pos);

byte[] bytes = new byte[size];

unsafe
{
    fixed (byte* pbytes = bytes)
    {
        *(Person*)pbytes = pos;
    }
}

 

 

Posted in C# | Leave a reply