質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ReactiveX

ReactiveX(Rx、Reactive Extensions)は、リアクティブプログラミングが可能なライブラリ。Java/Android用のRxJava、JavaScript用のRxJSなどさまざまな言語向けに実装されています。

Rx.NET

Rx.NETは、リアクティブプログラミングが可能なライブラリの一つ。.NET Framework向けReactive Extensionsライブラリです。マイクロソフト社が初めてRxライブラリとして提供し、ここから多くの言語にRxが移植されるようになりました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

1回答

1687閲覧

【C#】【Rx】Observable.FromEventメソッドの引数が何を表現しているのかが分かりません

galmacher

総合スコア37

ReactiveX

ReactiveX(Rx、Reactive Extensions)は、リアクティブプログラミングが可能なライブラリ。Java/Android用のRxJava、JavaScript用のRxJSなどさまざまな言語向けに実装されています。

Rx.NET

Rx.NETは、リアクティブプログラミングが可能なライブラリの一つ。.NET Framework向けReactive Extensionsライブラリです。マイクロソフト社が初めてRxライブラリとして提供し、ここから多くの言語にRxが移植されるようになりました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

1クリップ

投稿2018/10/14 02:02

編集2018/10/14 02:05

Rxの勉強をしており、.NETのイベントハンドラ(今回はMouseMoveイベント)を、
IObservableシーケンスに変換してくれるFromEventメソッドの理解を深めようとしています。
ネットのサンプルコードを見ていると以下のようなコードによく出くわします。

IObservable<MouseEventArgs> mouseMove = Observable.FromEvent<MouseEventHandler, MouseEventArgs>( h => (s, e) => h(e), h => this.MouseMove += h, h => this.MouseMove -= h);

これはFromEventメソッドの中でも下記オーバーロードを利用している認識です。

IObservable<TEventArgs> FromEvent<TEventHandler, TEventArgs>(    Func<Action<TEventArgs>, TEventHandler> conversion,    Action<TEventHandler> addHandler,    Action<TEventHandler> removeHandler)

この3つの引数とサンプルコードの引数がどのように対応しているのかを教えていただきたいです。
現段階では引数1:conversionについて考えて迷路に迷い込んでいる状態です。
仰々しく書くと
『引数convserionに「イベント情報(TEventArgs)を引数として受け取るデリゲート(Action)」を渡してください。戻り値でイベントハンドラ(TEventHandler)を返却します。』
という理解なのですが、それがなぜhだのsだのeだので表現出来ているのかが謎です。
どなたか分かりやすくご説明いただけないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ラムダ式です。
それがわかれば理解できます。
わからなければ理解できません。

ラムダ式についてはラムダ式っていうのが分かりません で書いたので詳細は省略します。
これでわからなければネット上に情報はたくさんありますので検索してみてください。

#追記

ラムダ式を使わず書いてみました。

C#

1using System; 2using System.Diagnostics; 3using System.Reactive.Linq; 4using System.Windows.Forms; 5 6namespace WindowsFormsApp1 7{ 8 public partial class Form1 : Form 9 { 10 public Form1() 11 { 12 InitializeComponent(); 13 } 14 15 private void button1_Click(object sender, EventArgs args) 16 { 17 Observable 18 .FromEvent<MouseEventHandler, MouseEventArgs>( 19 //h => (s, e) => h(e), 20 Conversion, 21 22 //h => this.MouseMove += h, 23 AddHandler, 24 25 //h => this.MouseMove -= h) 26 RemoveHandler) 27 .Subscribe(e => 28 { 29 Debug.WriteLine($"({e.X},{e.Y})"); 30 }); 31 } 32 33 private MouseEventHandler Conversion(Action<MouseEventArgs> h) 34 { 35 void action(object s, MouseEventArgs e) 36 { 37 h(e); 38 } 39 return action; 40 } 41 42 private void AddHandler(MouseEventHandler h) 43 { 44 MouseMove += h; 45 } 46 47 private void RemoveHandler(MouseEventHandler h) 48 { 49 MouseMove -= h; 50 } 51 } 52}

FromEvent の引数として、Conversion, AddHandler, RemoveHandler のデリゲートを渡しています。
FromEvent はまず AddHandler を呼び出し、マウスイベントにイベントハンドラを登録します。
そして必要な処理が終われば RemoveHandler を呼び出し、イベントハンドラを削除します。
そして Mouse イベントが起こるたびに Conversion から返された action を呼び出します。
h は FromEvent の登録したデリゲートで、これを呼び出すことにより、以降のオブザーバーに e を渡します。

#追記

Observable.FromEvent の中ではだいたいこんなことが行われていると思います。

C#

1using System; 2using System.Collections.Generic; 3using System.Diagnostics; 4using System.Reactive.Linq; 5using System.Windows.Forms; 6 7namespace WindowsFormsApp1 8{ 9 public partial class Form1 : Form 10 { 11 public Form1() 12 { 13 InitializeComponent(); 14 } 15 16 private void button1_Click(object sender, EventArgs args) 17 { 18 MyObservable<MouseEventHandler, MouseEventArgs> 19 .FromEvent( 20 h => (s, e) => h(e), 21 h => MouseMove += h, 22 h => MouseMove -= h) 23 .Subscribe(e => 24 { 25 Debug.WriteLine($"({e.X},{e.Y})"); 26 }); 27 } 28 } 29 30 class MyObservable<TEventHandler, TEventArgs> : IObservable<TEventArgs> 31 where TEventArgs : EventArgs 32 where TEventHandler : MulticastDelegate 33 { 34 protected IList<IObserver<TEventArgs>> Observers { get; } = new List<IObserver<TEventArgs>>(); 35 protected Action<TEventHandler> AddHandler { get; private set; } 36 protected Action<TEventHandler> RemoveHandler { get; private set; } 37 protected TEventHandler EventHandler { get; private set; } 38 39 public static IObservable<TEventArgs> FromEvent( 40 Func<Action<TEventArgs>, TEventHandler> conversion, 41 Action<TEventHandler> addHandler, 42 Action<TEventHandler> removeHandler) 43 { 44 var result = new MyObservable<TEventHandler, TEventArgs>(); 45 result.AddHandler = addHandler; 46 result.RemoveHandler = removeHandler; 47 result.EventHandler = conversion(result.Handler); 48 result.AddHandler?.Invoke(result.EventHandler); 49 return result; 50 } 51 52 private void Handler(TEventArgs e) 53 { 54 foreach (var observer in Observers) 55 { 56 observer.OnNext(e); 57 } 58 } 59 60 public IDisposable Subscribe(IObserver<TEventArgs> observer) 61 { 62 Observers.Add(observer); 63 return new Disposable(this, observer); 64 } 65 66 protected void RemoveObserver(IObserver<TEventArgs> observer) 67 { 68 if (Observers.Count == 0) return; 69 Observers.Remove(observer); 70 if (Observers.Count == 0) 71 { 72 RemoveHandler?.Invoke(EventHandler); 73 } 74 } 75 76 class Disposable : IDisposable 77 { 78 protected MyObservable<TEventHandler, TEventArgs> Owner { get; private set; } 79 protected IObserver<TEventArgs> Observer { get; private set; } 80 81 public Disposable(MyObservable<TEventHandler, TEventArgs> owner, IObserver<TEventArgs> observer) 82 { 83 Owner = owner; 84 Observer = observer; 85 } 86 87 public void Dispose() 88 { 89 if (Owner == null) return; 90 Owner.RemoveObserver(Observer); 91 Owner = null; 92 } 93 } 94 } 95}

投稿2018/10/14 04:21

編集2018/10/14 09:47
Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

galmacher

2018/10/14 05:21 編集

ご回答ありがとうございました。 リンクを貼っていただいている内容はシンプルな例をご記載いただいているので理解できました。 ただし今回挙げたサンプルコードが何をやっているのかについてはやはり理解できませんでした。
Zuishin

2018/10/14 07:54

追記しました。
galmacher

2018/10/14 12:35

ありがとうございます。 Conversionの部分は、まだ消化するのに時間が要りそうですが、ラムダ式を分解してくださったおかげでずいぶんすっきりしました。 追記部分も実際に動かしつつ追って動きを確認してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問