2016-05-27 16 views
1

私はアクションが実行されたときに何かを記録する拡張メソッドを持っています。実装はそうのようなものです:アクションとアクションを一般化する方法はありますか<T>?

public static Action Log(this Action action, string log) { 
    return (() => { 
     Console.WriteLine(log); 
     action(); 

    }); 
} 

しかし、私はまたAction<T>するアクションを許可します。これを一般化する方法があるので、logが記録されますが、アクションの署名は変更されませんか?

また、ActionAction<T>の2つの方法が必要ですか?

答えて

3

別個の方法が必要ですが、 Nコードの重複を減らすために他の面で1を実装する:あなたはLog(Action action, string log)を既存考える

、あなたが追加することができます。

public static Action<T> Log<T>(this Action<T> action, string log) { 
    return t => Log(() => action(t), log); 
} 

あるいは他の方法で回避:

public static Action<T> Log(this Action<T> action, string log) { 
    return t => { 
     Console.WriteLine(log); 
     action(t); 
    }); 
} 

public static Action Log(this Action action, string log) { 
    return() => Log<object>(t => action(), log); 
} 
2

ActionAction<T>は、このシナリオでは互換性がないため、2つの方法が必要です。

Actionが実際にはAction<void>の場合、この動作を有効にすると便利ですが、そうではありません。

+0

をうん、スウィフトは、やってできますそれは 'Void'はそれ自身のデータ型です。私はC#もこれを可能にするかどうか疑問に思っていた。 – vrwim

2

あなたはタイプDelegateを使用して、このようなparam object[]としてあなたのアクションの引数を提供することができます:これは、この出力になり

Action<int> testAction = i => Console.WriteLine($"Test: {i}"); 
testAction.Log("Logging", 42).Invoke(); 

public static Action Log(this Delegate action, string log, params object[] args) 
{ 
    return() => 
    { 
     Console.WriteLine(log); 
     action.DynamicInvoke(args); 
    }; 
} 

あなたはそのようなこの拡張機能を使用することができます

Logging 
Test: 42 
+0

ああ、OPが 'Log 'が 'Action 'を返そうとしていたという印象を受けました。(アクションのパラメータが 'Log'に渡されないことを意味します) - OPはそれを指定しませんでした。あなたはあなたの解釈で正しいかもしれません。 – hvd

+0

はい、これは私が気にしていたことではありません。私は、結果として生じる 'Action'を保存し、後でそれを呼び出すことを望みました。しかしこれは面白い解決策ですが、ある種の「動的パターン」を伴うので、+1 – vrwim

+0

Upvoteがいいです。私たちはC#で静的型付けされた言語なので、@ hvdの解決策ははるかに優れています。また、.NETベースのフレームワークとそこで利用可能なほとんどのライブラリで見つけたものと一貫しています。 –

関連する問題