かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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