C#+WPFチューニング戦記

C#とWPFで高速なコードと最適なシステムを書くためにやってきたいろいろな事を書いてみます。.NET Frameworkのソースコードを読み解きましょう。なお、ここに書かれているのは個人の見解であって何らかの団体や企業の見解を代表するものではありません。

共変性と反変性のこと、無法なobjectを撤廃する事

C#に触れていると嫌でも出てくる共変性と反変性のこと。
これを合理的に扱えずに悩んだことはありますか?
そんなあなたにC#的処方。

あんまり、ここしばらくリファレンスコードのことばかり書いたので、少しは普通のコードを論理的に綺麗にまとめる手法を提案したいと考えています。

interface IRecyclableItemCore
{
    void Release();
}

interface IRecyclableItem<in T> : IRecyclableItemCore
{
    void Initialize<T>(T param);
}

class RecyclableElement : FrameworkElement, IRecyclableItem<ViewModel>
{
    // 中身のことは後日
}

// さて、これを使うケースとは何でしょう。

これがどんな局面で役立つか、分かる人は鋭いと思います。一見、ただのインターフェース継承ですが、インターフェース継承とジェネリックには特異な利点があります。

  1. 外部から共変性が求められる部分を上記 IRecvclableItemCore のように記述できること
  2. 内部で反変性が求められる部分を上記 IRecyclableItem のように記述できること
  3. ジェネリック型パラメータの利用により、上記の2つの特性を1つのクラスに共存させることができること

共変性と反変性はコードの安全性に欠かせません。これを正しく扱うことは大切です。
このコードの使い方の答えは次回にでも。簡単に言うと、高速仮想化パネルの制作に必要だいうだけです。皆さんはWPFにとって劣悪な条件下でも高速なパネルというキーワードに魅力を感じないでしょうか。

散々速度のこと書いてきましたが、速度を重視するばかりでコードの保守性を損なってはいけません。コードの最速性は重要視しつつ、保守性もしっかりフォローというのが大切です。(今日の目的です)

これを基底のインターフェースとするなら、どんな仮想化クラス、仮想化パネルが生まれるのでしょう。ここから先は物語のような様相を呈しますので、しばしのお時間をいただくことになるかと思います。

一言、DataContextのようにあちこちをobjectで扱うインターフェースを使うのは気持ちの良いものではありません。
正しい方法さえ示されていれば、DataContextですらジェネリックに扱うことができたはずなのですが、そうはなっていません。
そもそも、あらゆる型を受け止めきる、万能のViewなど不可能なのですから。
つまり、Viewが受けるべきViewModelの情報は、なんだかんだでViewの形容にある程度束縛されるのです。少なくともViewは特定名称の依存関係プロパティを欲するのですから。欲しいプロパティをインターフェイスとして要求するのは有りではないかと思います。

なぜDependencyPropertyはジェネリックではないのでしょうか?(その問いに答えがない限り、我々は依然ボックス化とアンボックス化のコストの奴隷です。)

さて、では間違いなく速度が出る、本当のCanvasに話を進めてまいりましょうか。(脱線多々となりそうですが。)

でもその前に一応、Microsoftがこの部分をジェネリックで記述しなかった全体的背景は書く必要がありますね。