コンストラクタの疑問

コンストラクタの呼び出し - hiziriexの日記の続きになります。
元々あのクラス定義は、

  1. デフォルトコンストラクタが呼ばれた場合には一定の要素数(例えば3)を指定して初期化
  2. 素数を指定してコンストラクタを呼び出した場合には{"hoge1", "hoge2", "hoge3"}のようなstring配列で初期化
  3. string配列を指定して呼び出した場合にはそのstring配列をメンバ変数に代入

といった処理のテストのために作ったものなんだ。
だけど、3を指定とか、式だけで処理できる内容なら特に問題ないのだが、文を書かなければならない処理が書けない。
不可能じゃないけど、そのためには別にメソッド定義してそれを呼び出さなければならない。
しかもコンストラクタ内での呼び出しなのでstaticメソッドである必要まである。

public class Hoge
{
    private string[] items;
    public Hoge()
        : this(3)
    {
        Console.WriteLine("Hoge() called");
    }
    public Hoge(int n)
        : this(hoge(n))
    {
        Console.WriteLine("Hoge(" + n + ") called");
    }
    private static string[] hoge(int n)
    {
        string[] items = new string[n];
        for (int i = 0; i < n; i++)
        {
            items[i] = "hoge" + (i + 1);
        }
        return items;
    }
    public Hoge(string[] items)
    {
        this.items = items;
        Console.WriteLine("Hoge(string[] items) called");
    }
}

現状こんなこんな感じになるんだけどいい解決策はないだろうか?
ごちゃごちゃしてまとまらないからこのまま公開します。

コンストラクタの呼び出し

Hogeクラスのコンストラクタを定義する。
クラス内で定義された他のコンストラクタを呼ぶにはthisを利用する。
この場合、thisで呼び出したコンストラクタがどのタイミングで呼び出されるか調べた。

public class Hoge
{
    public Hoge()
        : this(3)
    {
        Console.WriteLine("Hoge() called");
    }
    public Hoge(int n)
        : this(new string[]{"hoge"})
    {
        Console.WriteLine("Hoge(int n) called");
    }
    public Hoge(string[] items)
    {
        Console.WriteLine("Hoge(string[] items) called");
    }
}

以下は呼び出し元のコード

new Hoge();
new Hoge(3);
new Hoge(new string[] { "hoge", "auau" });

出力は以下のようになった。

Hoge(string items) called
Hoge(int x) called
Hoge() called
Hoge(string items) called
Hoge(int x) called
Hoge(string[] items) called

以上より、thisで呼び出されるコンストラクタの後に通常の処理が実行されていることがわかる。

Textプロパティのデザイナを複数行に変更

Labelコントロールの様に、プロパティエディタで値を変更するときに複数行エディタがポップアップするように、変更したい。

class HogeControl : System.Windows.Forms.Control
{
    [System.ComponentModel.Editor(
        typeof(System.ComponentModel.Design.MultilineStringEditor),
        typeof(System.Drawing.Design.UITypeEditor))]
    public override string Text { get; set; }
}

とすれば、今のところ正常に動いている。
親クラスのプロパティでないならoverrideはいらない。

C#からWin32APIを呼び出してみた

ほぼ見よう見真似でやってみた。

using System;
using System.Drawing;
using System.Runtime.InteropServices;//DllImportに必要
public class WinApi
{
        //よくわからないけどたぶんメモリ上に連続してデータ並べるってこと
        [StructLayout(LayoutKind.Sequential)]
        //Win32APIで使うデータって.netでは一切定義されてないから定義しないとダメ
        public struct RECT
        {
            public Int32 left, top, right, bottom;
            //コンストラクタ?構造体なんであまり関係ないような気もする。
            //Setterみたいなもんです。たぶん。
            public RECT(Rectangle rect)
            {
                left = rect.Left;
                top = rect.Top;
                right = rect.Right;
                bottom = rect.Bottom;
            }
        }
        //ExtTextOutWはgdi32.dllにあるんですね。知らんけどね。
        //文字コードをUnicodeに指定ってのは、なんとなくわかった。
        [DllImport("gdi32.dll", CharSet = CharSet.Unicode)]
        private static unsafe extern bool ExtTextOutW(IntPtr hdc, Int32 X,
                Int32 Y, UInt32 fuOptions, RECT* lprc, string lpString,
                UInt32 cbCount, IntPtr lpDx);
        public static bool ExtTextOut(IntPtr hdc, Int32 X, Int32 Y,
                UInt32 fuOptions, RECT* lprc, string lpString,
                UInt32 cbCount, IntPtr lpDx)
        {
                unsafe
                {
                        ExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx);
                }
        }
}

みたいな風に定義しといて、呼び出すときは、また今度にしよう。
これでフォームに文字列を描画できるようになりました。
.netの標準機能でもできるけどね。