2

ここで風邪を引いObservableていて、「グループ化」を数回購読しているのに、なぜここで公開する必要がないのですか?実行すると望ましくない結果が生じると予想していましたが、驚いたことに、公開の有無にかかわらず機能します。何故ですか?

var subject = new List<string>
    {                            
    "test",                        
    "test",                 
    "hallo",
    "test",
    "hallo"
    }.ToObservable();
subject
    .GroupBy(x => x)
    .SelectMany(grouped => grouped.Scan(0, (count, _) => ++count)
         .Zip(grouped, (count, chars) => new { Chars = chars, Count = count }))
    .Subscribe(result => Console.WriteLine("You typed {0} {1} times", 
         result.Chars, result.Count));

// I Would have expect that I need to use Publish like that
//subject
//   .GroupBy(x => x)
//   .SelectMany(grouped => grouped.Publish(sharedGroup => 
//       sharedGroup.Scan(0, (count, _) => ++count)
//       .Zip(sharedGroup, (count, chars) => 
//           new { Chars = chars, Count = count })))
//   .Subscribe(result => Console.WriteLine("You typed {0} {1} times", 
//       result.Chars, result.Count));

Console.ReadLine();

編集

Paulが気付いたように、基礎となるコールドオブザーバブルを2回サブスクライブしているので、シーケンスを2回確認する必要があります。しかし、私はこの効果を目に見えるようにすることができませんでした。デバッグ行を挿入しようとしましたが、たとえば、これは「実行中」を1回だけ出力します。

var subject = new List<Func<string>>
{                            
() =>
    {
        Console.WriteLine("performing");
        return "test";
    },                        
() => "test",                 
() => "hallo",
() => "test",
() => "hallo"
}.ToObservable();


subject
    .Select(x => x())
    .GroupBy(x => x)
    .SelectMany(grouped => grouped.Scan(0, (count, _) => ++count)
            .Zip(grouped, (count, chars) => new { Chars = chars, Count = count }))
    .Subscribe(result => Console.WriteLine("You typed {0} {1} times",
            result.Chars, result.Count));

コールドオブザーバブルを扱っていて、使用していないという効果を可視化できるのではないかと思いますPublish()。別のステップでは、(上記を参照)どのようにPublish()効果がなくなるかを確認したいと思います。

編集2

Paulが提案したように、私IObservable<string>はデバッグ目的でカスタムを作成しました。ただし、そのメソッドにブレークポイントを設定すると、一度Subscribe()だけヒットすることに気付くでしょう。

class Program
{
    static void Main(string[] args)
    {
        var subject = new MyObservable();

        subject
            .GroupBy(x => x)
            .SelectMany(grouped => grouped.Scan(0, (count, _) => ++count)
                 .Zip(grouped, (count, chars) => new { Chars = chars, Count = count }))
            .Subscribe(result => Console.WriteLine("You typed {0} {1} times",
                 result.Chars, result.Count));

       Console.ReadLine();
   }
}

class MyObservable : IObservable<string>
{
    public IDisposable Subscribe(IObserver<string> observer)
    {
        observer.OnNext("test");
        observer.OnNext("test");
        observer.OnNext("hallo");
        observer.OnNext("test");
        observer.OnNext("hallo");
        return Disposable.Empty;
    }
}

だから私にとって、質問はまだ開いています。なぜ私はPublishこの寒さでここを必要としないのObservableですか?

4

2 に答える 2

6

リストベースのソースを使用しているのは1回だけなので、サブスクリプション効果が重複することはありません。あなたの質問に答えるための鍵は、次の観察です:

GroupByから流出するIGroupedObservable<K、T>オブジェクトは、それ自体が偽装されたサブジェクトです。

内部的には、GroupByはDictionary <K、ISubject<T>>を保持します。メッセージが着信するたびに、対応するキーを使用して件名に送信されます。サブジェクトがプロデューサーをコンシューマーから切り離すため、グループ化オブジェクトを2回サブスクライブします。これは安全です。

于 2011-11-15T20:52:50.097 に答える
1

Zipで「grouped」を再利用するということは、各グループ化を2回効果的に実行していることを意味します。ただし、ソースがColdであるため、引き続き機能します。それは理にかなっていますか?

于 2011-11-13T00:37:32.933 に答える