UniRxはSubscribeされるまではオペレータは評価されないし勝手に死ぬ

UniRxの寿命管理はしっかりしているらしく、`UpdateAsObservable()`とかはとても便利で、基本的に`MonoBehavior`は`GameObject`とと寿命を共にすることが多いので、`MonoBehavior`のコンポーネントが死ぬときには`GameObject`と共にある`UpdateAsObservable()`も根こそぎ死んでくれます。

ですが、今回は`MonoBehavior`でないクラスにContextとしてGameObjectを与え、自分自身で寿命管理をさせたくなりました。すると、当たり前のように次のように書いていましたが

```cs
this.inputStream = gameObject.UpdateAsObservable()
    .Select(_=> Input.GetKeyDown(KeyCode.A));

// その後、this.inputStream を使ったり使わなかったりする
```

あれ？寿命大丈夫かな？と不安になってきました。
Linqは`Count()`とか`ToList()`しないとそこまでのオペレータも評価されないですし、Rxもそうだというようなことを聞いてはいましたが、ちょっと確かめてみないと気が済まなくなったので、順を追ってみていきたいと思います。

引用・参考 [neuecc/UniRx](https://github.com/neuecc/UniRx)
※ コードや表現はUniRxのコードを引用していますが、かなり簡略化しています。マサカリは歓迎ですが、あんまり苛めないでね！

# コードトレース

## `Subject`に何もオペレータがついてない状態で`OnNext()`されたとき

```cs
class Subject
{
    IObserver<T> outObserver = EmptyObserver<T>.Instance;

    // コンストラクタは無い

    public void OnNext(T value)
    {
        outObserver.OnNext(value);
    }
}
```
`EmptyObserver`に伝わるので何も起きない。

## `Subject.Select(selector)`のとき

```cs
public static IObservable<TR> Select<T, TR>(this IObservable<T> source, Func<T, TR> selector)
{
    return new SelectObservable<T, TR>(source, selector);
}

class SelectObservable
{
    public SelectObservable(IObservable<T> source, Func<T, TR> selector)
        : base(source.IsRequiredSubscribeOnCurrentThread())
    {
        this.source = source;
        this.selector = selector;
    }
}
```

`Subject.outObserver`は`EmptyObserver`のままなので、やはり何も起きない。（selectorは動かない）
`Subject.Subscribe(observer)`も呼ばれていないので、`Subject`のインスタンス自体が基本的に変化していないのである。

## `Subject.Select(selector)`のときに`Subject.OnNext()`が呼ばれたとき

`Select(selector)`したときのように、そもそも`Subject.outObserver`が変化していないので、selectorはやはり呼ばれない。

## `Subject.Select(selector).Subscribe(observer)`されたとき

```cs
class SelectObservable
{
    protected override IDisposable SubscribeCore(IObserver<TR> observer, IDisposable cancel)
    {
        // sourceはここではSubjectのインスタンス
        return source.Subscribe(new Select_(this, observer, cancel));
    }
}

class Subject
{
    IObserver<T> outObserver = EmptyObserver<T>.Instance;

    public IDisposable Subscribe(IObserver<T> observer)
    {
        // 本当はもっとごちゃごちゃしてる
        outObserver = listObserver.Add(observer);
        return new Subscription(this, observer);
    }
}
```

ここで初めて`Subject`インスタンスに変化が起こり、`OnNext()`が伝播し始める（selectorを通るようになる）

## `Subscription.Dispoese()`したら？

```cs
class Subscription : IDisposable
{
    Subject<T> parent;
    IObserver<T> unsubscribeTarget;

    public Subscription(Subject<T> parent, IObserver<T> unsubscribeTarget)
    {
        this.parent = parent;
        this.unsubscribeTarget = unsubscribeTarget;
    }

    public void Dispose()
    {
        // ここでのペアレントはSubjectのインスタンス
        parent.outObserver = listObserver.Remove(unsubscribeTarget);
    }
}
```
`Subscribe`のときの完全な逆操作ですね。

# 寿命についての結論

やはり、`Select()`は新しいオブジェクトを生成して返しており、`Subject`に参照を渡してはいません。つまり`Select()`の返り値への参照がなくなれば勝手にGCされます。`Subscribe`した時だけは、`OnComplete`するまで返り値の`Subscription`を握って適切に`Dispoese()`する必要があります。

時間の都合でそこまで読んでいませんが、恐らく`Where()`などのオペレータも同じだと思います。ただ、`Buffer()`系のは実質的に一旦`Subscribe()`して新しいStreamを返していそうですね。（要確認）しかしこれも、以上の流儀に従うならば、`Subscribe()`されていときしか`Subject`に参照を渡していなさそうに思います。