36216


こんにちは。

C#で、遅延実行をしようとしています。  
ある程度は動いています。

下記のソースを定義しました。

[code]

    public static void WaitExecute(int milliseconds, Action f)
    {
        // 指定秒後に処理を実行
        DispatcherTimer timer = new DispatcherTimer
        {
            Interval = TimeSpan.FromMilliseconds(milliseconds)
        };
        timer.Start();
        timer.Tick += (s, args) =>
        {
            // タイマーの停止
            timer.Stop();
            f();
        };
    }
    
    private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        // 指定秒後に処理を実行
        WaitExecute(100, () =>
        {
            comboBox1.Text = "デフォルト値";
        });
    }
    
[/code]

このようにして、少しだけ動作を遅らせて動かす仕組みを作ってみました。  
comboBoxは単なる例です。  
Comboboxで何を選択しても、すぐにデフォルト値に戻るような動きをします。  
(実際には特定の項目だけデフォルト値に戻る、  
というような実装をしています)

このときに、この、`WaitExecute`に引数として、引き数なしの`Action`を渡すだけではなく  
引き数が任意個数の、たとえば、`Action<string>` や `Action<string, string>`や  
`Action<int>` などを渡したいのです。

`WaitExecute`を修正して`Action`を引き渡したときに  
ジェネリックとして記載するのだと思うのですが、  
そのやり方がわかりません。

検索ワードの工夫も難しくテクニックなどがみつかりませんでした。

ご存知でしたら教えてください。

このようなテクニックがわかるWebサイトなどを  
示していただくのも助かります。

よろしくお願いします。


CC BY-SA 3.0
2017-07-09T09:36:59.743
36215
2017-07-09T10:55:00.203
2017-07-09T09:51:43.413
4236
21047
question
c#
C#で遅延実行を書いたがActionをジェネリックで渡す方法がわからない


`Action<string>`を実行するには`string`引数が必要ですし、`Action<string,
string>`を実行するには２つの`string`引数が必要なわけで、

  * `WaitExecute(int milliseconds, Action f)`
  * `WaitExecute<T0>(int milliseconds, Action<T0> f, T0 s0)`
  * `WaitExecute<T0, T1>(int milliseconds, Action<T0, T1> f, T0 s0, T1 s1)`

と引数ごとに異なるシグネチャになります。C#言語ではこれらをひとつにまとめて記述する機能はないため、適切な検索キーワードもありませんし、見つからないのも当然ではあります。余談ですが、C++言語では[Variadic
Templates（可変引数テンプレート）](https://cpprefjp.github.io/lang/cpp11/variadic_templates.html)という機能で記述できます。

さてC#言語ではそれぞれのメソッドを記述する必要がありますが、この例であれば実現するほどのメリットがあるか疑問です。

なお単に遅延させるだけであれば[`Task.Delay`メソッド](https://msdn.microsoft.com/ja-
jp/library/system.threading.tasks.task.delay\(v=vs.110\).aspx)が用意されています。

[code]

    private async void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        await Task.Delay(100);
        comboBox1.Text = "デフォルト値";
    }
    
[/code]


CC BY-SA 3.0
2017-07-09T09:50:31.213
36216
2017-07-09T09:57:08.063
2017-07-09T09:57:08.063
4236
4236
36215
answer


シグネチャを

[code]

    void WaitExecute<T>(int milliseconds, Action<T> f, T arg)
    
[/code]

や

[code]

    void WaitExecute<T1, T2>(int milliseconds, Action<T1, T2> f, T1 arg1, T2 arg2)
    
[/code]

として`f()`を`f(arg)`や`f(arg1, arg2)`で置き換え、

[code]

    WaitExecute(ms1, Method1, 10);
    WaitExecute(ms2, Method2, "foo", "bar");
    
[/code]

のように呼び出すメソッドを想定しておられるものと思いますが、引数を`f`を実行するためだけに使用するのであれば、

[code]

    WaitExecute(ms1, () => Method1(10));
    WaitExecute(ms2, () => Method2("foo", "bar"));
    
[/code]

のように`Action`でラップして実行すれば事足りるのでは。


CC BY-SA 3.0
2017-07-09T10:55:00.203
36218
2017-07-09T10:55:00.203
5750
36215
answer