かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Reactive Extensions再入門 その32「型変換を行うCastとOfTypeメソッド」

過去記事インデックス

はじめに

今回は型変換です!

型変換を行う拡張メソッド

ここでは、IObservableのシーケンスに対して型変換を行うメソッドについて説明します。

Castメソッド

ここではCastメソッドについて説明します。Castメソッドは名前の通り、もとになるIObservableのシーケンスから発行された値をキャストして後続に流します。メソッドのシグネチャを以下に示します。

public static IObservable<T> Cast<T>(this IObservable<object> source);

このメソッドの使用例を下記に示します。

var source = new Subject<object>();
source
    // 値をint型にキャスト
    .Cast<int>()
    // 購読
    .Subscribe(
        i => Console.WriteLine("OnNext({0})", i),
        ex => Console.WriteLine("OnError({0})", ex),
        () => Console.WriteLine("OnCompleted()"));

// int型の値を発行
source.OnNext(1);
source.OnNext(2);
source.OnNext(3);

// 文字列型を発行してみる
source.OnNext("abc");

Castメソッドを使ってobject型からint型に変換してSubscribeで購読しています。そして、1〜3の値を発行したあとに文字列型の”abc”を発行しています。実行結果を以下に示します。

OnNext(1)
OnNext(2)
OnNext(3)
OnError(System.InvalidCastException: 指定されたキャストは有効ではありません。
   場所 System.Reactive.Linq.Observable.<Cast>b__46e[TResult](Object x)
   場所 System.Reactive.Linq.Observable.<>c__DisplayClass408`2.<>c__DisplayClass
40a.<Select>b__407(TSource x))

実行結果からわかる通り、文字列型を発行するとInvalidCastExceptionが発行されてOnErrorに処理がいっていることが確認できます。このようにCastメソッドは、あくまで単純なキャストを行うためのメソッドであることがわかります。

OfTypeメソッド

ここでは、OfTypeメソッドについて説明します。OfTypeメソッドは、もとになるIObservableのシーケンスから指定した型でフィルタリングを行うメソッドになります。メソッドのシグネチャを以下に示します。

public static IObservable<T> OfType<T>(this IObservable<object> source);

このメソッドのコード例を下記に示します。

var source = new Subject<object>();
source
    // int型のみを通過させる
    .OfType<int>()
    // 購読
    .Subscribe(
        i => Console.WriteLine("OnNext({0})", i),
        ex => Console.WriteLine("OnError({0})", ex),
        () => Console.WriteLine("OnCompleted()"));

// int型の値を発行
source.OnNext(1);
source.OnNext(2);
source.OnNext(3);

// 文字列型を発行してみる
source.OnNext("abc");
source.OnNext("4");

// もう一度int型の値を発行して終了
source.OnNext(100);
source.OnCompleted();

OfTypeメソッドを使って、1〜3の値が発行されたあと文字列型で”abc”と”4”が発行されて、100が発行されるシーケンスをフィルタリングして、購読しています。実行結果を以下に示します。

OnNext(1)
OnNext(2)
OnNext(3)
OnNext(100)
OnCompleted()

Castメソッドとは異なり、文字列型が発行されても例外は発生しません。単純に後続に値が流れることなくフィルタリングされます。