kazuk は null に触れてしまった

C# / .NET 系技術ネタ縛りでお送りしております

Observable.CombineLatest に渡された要素のどっちが先?


暇ってわけじゃないんだけど、@igetaさんのツイートが琴線に触れたので書いてみた。

xs.CombineLatest(ys, (x, y) => { … }) したときの push の後先(x -> y の順で push されたか y -> x の順で push されたか)を識別するうまい方法ってないんかな?

単純にタイムスタンプを一回付けてから引っぺがすだけ。

    public static class ReactiveEx
    {
        private static long _currentStamp;
        static long GetStamp()
        {
            return System.Threading.Interlocked.Increment(ref _currentStamp);
        }

        private class StampedItem<T>
        {
            public T Item { get; set; }
            public long Stamp { get; set; }
        }

        public static IObservable<TResult> CombineLatest<TLeft, TRight, TResult>(
            this IObservable<TLeft> leftSource,
            IObservable<TRight> rightSource,
            Func<TLeft, TRight, bool, TResult> selector )
        {
// ReSharper disable InvokeAsExtensionMethod
            return Observable.CombineLatest(
                leftSource.Select(leftItem => new StampedItem<TLeft> {Item = leftItem, Stamp = GetStamp()}), 
                rightSource.Select(rightItem => new StampedItem<TRight> {Item = rightItem, Stamp = GetStamp()}),
                (left,right) => selector( left.Item, right.Item, left.Stamp>right.Stamp ));
// ReSharper restore InvokeAsExtensionMethod
        }
    }

「Rxの神が出てくる前にネタは潰しておかなければならない。」等とは思っていない。

って書いたすぐに

神が出てきて

@kazuk @igeta Timestampというそのものなメソッドがあったりするので、細かい調整がしたい場合は、やっぱそれ使ってね、ということだと思います。と、さっきまで他に何か手はないかなー、と考えてたけど浮かびませんでした:)

Timestampを自作する必要なんて無いかもーって思って書き変えた。

    public static class ReactiveEx
    {
        public static IObservable<TResult> CombineLatest<TLeft, TRight, TResult>(
            this IObservable<TLeft> leftSource,
            IObservable<TRight> rightSource,
            Func<TLeft, TRight, bool, TResult> selector )
        {
// ReSharper disable InvokeAsExtensionMethod
            return Observable.CombineLatest(
                leftSource.Timestamp(), 
                rightSource.Timestamp(),
                (left,right) => selector( left.Value, right.Value, left.Timestamp<right.Timestamp ));
// ReSharper restore InvokeAsExtensionMethod
        }
    }

Timestamp がDateTimeOffsetってのは間隔次第ではきっとかぶるよねーって事で、本気にどっちが先かの厳密性を追う用途の場合には前バージョンを、そうでない場合には後者を使う事になると思います。

という訳で書いてみる事で新たな知識を得たと。

しかし、Rx のメソッド検索すると Windows Phone の方のリファレンスに飛ばされる…。</P

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。