C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2007/05/31 12:37
ついにリリースされました、日本語版 "Windows Vista™ および .NET Framework 3.0 ランタイム コンポーネント用 Microsoft® Windows® Software Development Kit" 。

英語版の SDK を既にインストールしてある場合は、アンインストールしてからのインストールとなります。 ( 詳しくは参考リンク先を参照してください。 )

ダウンロードの詳細 : Microsoft Windows SDK for Windows Vista



これでやっと、WCF の日本語ドキュメントが読めます^^


[ 参考 ]
Software Cafe : Windows SDK for Windows Vista and .NET Framework 3.0 日本語版


[ 関連記事 ]
C#と諸々 - .NET Framework 3.0 正式版 リリース
スポンサーサイト



タグ: .NET SDK
2007/05/27 23:11
"物品" と "ケース" というクラスがあります。
"物品" は "CD" や "ペン" などの総称です。"ケース" は "物品" をなんでも格納できます。
"物品" は抽象的なものですが、"ケース" は具体的なものです。
さらに、"CD" だけを格納できる "CDケース" と、"ペン" だけを格納できる "ペンケース" があります。

この時、"物品" と "CD" の間に継承関係は成り立つでしょうか?また、"ケース" と "CDケース" の間に継承関係は成り立つでしょうか?


継承関係とは 「is - a」 の関係です。つまり、「"CD" は "物品" である」と言えるなら、"物品" と "CD" の間に継承関係が成り立ちます。「"CDケース" は "ケース" である」 と言えるなら、"ケース" と "CDケース" の間に継承関係が成り立ちます。

この2つはどちらも成り立ちそうな気がします。しかし、実際成り立つのは "物品" と "CD" の継承関係だけです。"ケース" と "CDケース" の継承関係は成り立ちません。

オブジェクト指向設計における原則の一つに「リスコフの置換原則」と言う原則があります。「基本クラスのインスタンスの代わりに派生クラスのインスタンスを使用できなければならない」といったものです。
" ケース" は "CD" 以外の "物品" も格納できる必要がありますが、"CDケース" には "CD" しか格納できません。よって、"CDケース" のインスタンスは "ケース" のインスタンスの代わりにはなれません。これではリスコフの置換原則に違反してしまいます。違反しているということは 「"CDケース" は "ケース" ではない」 ということになります。


図 1. "CD ケース" は "ケース" ではない

普通に考えて、「CDケースはケースではない」 なんて、おかしな話です。なぜこんなことになってしまうのでしょうか?
実は、"ケース" の定義に誤りがあります。"ケース" は "物品" をなんでも格納できるのではなく、「なんらかの "物品" 」 を格納できるものであるべきなのです。"物品" をなんでも格納できるのは "ケース" ではなく "物品ケース" というような別のクラスにするべきです。
言い換えると、「"ケース" という名前は適切じゃないから "物品ケース" に変更して、"ケース" という基本クラスを別に用意しよう」 ということです。 ( 物品ケースという名前も不適切だと思う場合は、 "万能ケース" などで読み替えてください。 )


" ケース" は 「なんらかの "物品" 」 を格納できます。この 「なんらかの "物品" 」 というのは派生クラスで定められます。"物品ケース" なら全ての "物品" 、"CDケース" なら "CD" となります。扱う "物品" が定まらないため、"物品" ( 及びその派生クラス ) と "ケース" の間には関連を結びません。"ケース" の派生クラスがそれぞれ関連を持つことになります。

図 2. "CD ケース" は "ケース" である

"ケース" は 「なんらかの "物品" 」 を格納できるのだから、コード 1-1 のように 「なんらかの "物品" 」 の格納を補助する機能・仕組みを備えることはできます。

コード 1-1. なんらかの"物品"の格納補助機能を備えた "ケース"
using System;
using System.Collections.Generic;
using System.Text;

public abstract class ケース
{
    private readonly List<物品> 格納物品コレクションフィールド;

    protected List<物品> 格納物品コレクション
    {
        get
        {
            return this.格納物品コレクションフィールド;
        }
    }

    protected ケース()
    {
        this.格納物品コレクションフィールド = new List<物品>();
    }

    protected void 物品の格納を補助(物品 対象物品)
    {
        this.格納物品コレクションフィールド.Add(対象物品);
    }

    protected 物品 物品の取り出しを補助(int 格納位置)
    {
        物品 取り出す物品 = this.格納物品コレクションフィールド[格納位置];
        this.格納物品コレクションフィールド.Remove(取り出す物品);
        return 取り出す物品;
    }
}


これを継承した "CDケース" が コード 1-2 になります。

コード 1-2. コード 1-1 の "ケース" を継承した "CDケース"
using System;
using System.Collections.Generic;
using System.Text;

public class CDケース : ケース
{
    public CD this[int 格納位置]
    {
        get
        {
            return (CD)this.格納物品コレクション[格納位置];
        }
    }

    public CDケース()
        : this(null)
    {
    }

    public CDケース(List<CD> 格納CDコレクション)
        : base()
    {
        if (格納CDコレクション != null)
        {
            foreach (物品 item in 格納CDコレクション)
            {
                base.格納物品コレクション.Add(item);
            }
        }
    }

    public void CDを格納(CD 対象CD)
    {
        base.物品の格納を補助(対象CD);
    }

    public CD CDを取り出す(int 格納位置)
    {
        return (CD)base.物品の取り出しを補助(格納位置);
    }
}


また、ジェネリックを利用すれば派生クラスはさらに簡単に作成できます。

コード 2-1. なんらかの"物品"の格納補助機能をジェネリックとして備えた "ケース"
using System;
using System.Collections.Generic;
using System.Text;

public abstract class ケース<T>
    where T : 物品
{
    private readonly List<T> 格納物品コレクションフィールド;

    protected List<T> 格納物品コレクション
    {
        get
        {
            return this.格納物品コレクションフィールド;
        }
    }

    public T this[int 格納位置]
    {
        get
        {
            return this.格納物品コレクション[格納位置];
        }
    }

    protected ケース()
        : this(new List<T>())
    {
    }

    protected ケース(List<T> 格納物品コレクション)
    {
        this.格納物品コレクションフィールド = 格納物品コレクション;
    }

    public void 物品を格納(T 対象物品)
    {
        this.格納物品コレクションフィールド.Add(対象物品);
    }

    public T 物品を取り出す(int 格納位置)
    {
        T 取り出す物品 = this.格納物品コレクションフィールド[格納位置];
        this.格納物品コレクションフィールド.Remove(取り出す物品);
        return 取り出す物品;
    }
}


これを継承した "CDケース" が コード 2-2 になります。

コード 2-2. コード 2-1 の "ケース" を継承した "CDケース"
using System;
using System.Collections.Generic;
using System.Text;

public class CDケース : ケース<CD>
{
    public CDケース()
        : base()
    {
    }

    public CDケース(List<CD> 格納CDコレクション)
        : base(格納CDコレクション)
    {
    }
}



ちなみに、物品側から親ケースを参照できるようにしようとした場合どうなるでしょうか?
" 物品ケース" は "物品" ならなんでも格納できるのだから、"物品" には親物品ケースというプロパティを持たせ、さらに、"CD" は親CDケース、"ペン" は親ペンケースというプロパティを別に持つ必要があります。ただ、これでは "CD" が "物品ケース" に格納されている場合と "CDケース" に格納されている場合があることになります。これでは複雑な設計となってしまうため、"物品" には親ケース プロパティを用意せず、"物品" の各派生クラス ( "CD", "ペン" )がそれぞれの親ケース プロパティを持つだけにした方がいいかもしれません。あるいは、なんでも格納できる "物品ケース" というある意味特別なクラスを元々用意しなければ、このような問題は起きず綺麗な設計になります。
なお、"物品ケース" をジェネリッククラスにした場合、 "物品" も同じようにジェネリックで親ケースを指定できるようにする、ということはできないことに注意します。これは、ジェネリックの型制約の指定がうまくできないためです。
→  解決方法がありました。詳細は C#と諸々 - ミラー階層とジェネリック を参照してください。


図 3. "物品ケース" を用意しない場合



最後になりましたが、このように複数のクラス階層間において、各クラス毎に同じような関連を結ぶモデルを、ミラー階層と呼びます。


[ 参考書籍 ]
オブジェクト開発の神髄


2007/05/12 03:00
何故か自宅の PC で SQL Server 2005 SP2 の インストール が必ず失敗する。Windows Update での インストール も、ダウンロード した インストーラ からの インストール も失敗する。
ずっとほったらかしてたんだけど、いい加減 タスクトレイ にWindows Update の通知 アイコン が常時表示されるのに嫌気がさしてきた (^ω^#)

環境はこんな感じ

SQL Server Express Edition with Advanced Services
Windows Vista


エラー内容はこんな感じ

マネージ オブジェクト形式 (MOF) のファイル c:\Program Files\Microsoft SQL Server\90\Shared\sqlmgmproviderxpsp2up.mof をコンパイルできませんでした。


SQL Server を一度 アンインストール してから再度 インストール してみたけど、結果は変わらず。で、 "sqlmgmproviderxpsp2up" でググってみたら・・・あった。

SQL 2005 Standard on Vista RTM - MSDN Forums


どうも、 WMI データベース とやらがおかしくなっていたみたい。
修復するには、コマンドプロンプト ( 管理者権限 ) で、以下の 3つの コマンド を順番に実行していくとのこと。

winmgmt /verifyrepository
winmgmt /salvagerepository
winmgmt /salvagerepository


実行結果はこんな感じ

C:\>winmgmt /verifyrepository
WMI データベースに矛盾があります

C:\>winmgmt /salvagerepository
WMI データベースの回収に失敗しました
エラー コード:  0x8007041B
機能:   Win32
説明:   別の実行中のサービスが依存しているサービスにストップ コントロールが送信
されました。


C:\>winmgmt /salvagerepository
WMI データベースが回収されました


おお、なんか成功したっぽいな。試しに一つ目の コマンド をもう一回実行してみると、矛盾はないって褒められた。
インストール ウィザード の エラー ダイアログ で再試行 ボタン を押してみると、、、進行した。
あとは特に問題も生じず、無事に インストール を完了。
いやぁ、やっと Windows Update が常時表示されなくなった。SP2 は色々な騒動を起こしていたけど、これは何が原因だったのやら。。。
タグ: .NET SQL_Server DB