2016-09-14 8 views
6

帰宅途中で私はアイデアを持っていました.Func/Action拡張を作成して、C#で素晴らしい構文糖を使用できるようにします。メソッドがfunc/action代理人のように構文的に機能しないのはなぜですか?

理論上の例...時間にメソッドの実行を、あなたを許すのFunc /アクションの様々な順列のための拡張機能を作成。

私が家に到着して例を試したとき、私はこれがおそらくないことを発見しました。私はそれがC#の欠点/不一致だと信じています。デリゲートとメソッドは同じ(理論上)のものです。

public static class Extensions 
{ 
    public static void Time(this Action action) 
    { 
     // Logic to time the action 
     action(); 
    } 
} 

public class Example 
{ 
    public void Main() 
    { 
     Action action = RunApp; 
     Action actionLambda =() => { }; 
     Action actionDelegate = delegate() { }; 

     Extensions.Time(RunApp); // Works 
     Extensions.Time(() => { }); // Works 
     Extensions.Time(delegate() { }); // Works 
     Extensions.Time(action); // Works 
     Extensions.Time(actionLambda); // Works 
     Extensions.Time(actionDelegate); // Works 

     action.Time(); // Works 
     actionLambda.Time(); // Works 
     actionDelegate.Time(); // Works 

     ((Action) RunApp).Time(); // Works 
     ((Action) delegate() { }).Time(); // Works 
     ((Action) (() => { })).Time(); // Works 

     // These should all be the same! 

     RunApp.Time(); // No good: "Example.RunApp() is a method which is not valid in the given context" 
     () => { }.Time(); // No good: Operator '.' cannot be applied to operand of type 'lambda expression'" 
     (() => { }).Time(); // No good: Operator '.' cannot be applied to operand of type 'lambda expression'" 
     delegate() { }.Time(); // No good: "Operator '.' cannot be applied operand of the type 'anonymous method'" 
    } 

    public void RunApp() 
    { 
     // Stuff... 
    } 
} 

私はのFunc /アクションを理解するには、デリゲートとメソッドのグループに比べてC#に新しい追加されているが、なぜそれらはすべて同じように行動することはできませんか?

+1

アクション。タイム(あなたのコードに示すように、明示的に –

+1

あなたの最後の行は、 '((アクション)(()=> {}))にする必要があるアクションとして何かをカプセル化するために言っている、方法をカプセル化するので、 ); ' –

+0

別の「作品」として追加し、オリジナルをリセットします。 – smdrager

答えて

0

アクションはちょうどうまく明示的にデリゲートを宣言することなく、簡単な方法でデリゲートをカプセル化します。 C#では、delegateはメソッドを型としてキャプチャするための言語メカニズムです。タイプは、言語が自動的にデルにメソッドをキャストしません、あなたが明示的に行う必要があり

public static class Extensions 
    { 
     public delegate void Del(); 
     public static void Time(this Del action) 
     { 
      // Logic to time the action 
      action(); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     {    
      ((Extensions.Del)(() => { })).Time(); 
     } 
    } 

...戻っ代表者に簡素化し、あなたがそう....上の拡張メソッドを作成するために必要なものです。メソッド自体は型ではなく、デリゲートはそれをキャプチャするメカニズムです。基本的に、C#では、デリゲートはメソッドと同じではありません。これは、メソッドへの類型のポインタを持つC#のソリューションです。

心に留めておくべきもう一つは、あなたが行うことができます: -

public static class Extensions 
    { 
     public delegate void Del(); 
     public delegate void Del2(); 
     public static void Time(this Del action) 
     { 
      // Logic to time the action 
      action(); 
     } 
     public static void Time(this Del2 action) 
     { 
      // Logic to time the action 
      action(); 
     } 


     public static void Time(this Action action) 
     { 
      // Logic to time the action 
      action(); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     {    

      ((Extensions.Del)(() => { })).Time(); 
      ((Extensions.Del2)(() => { })).Time(); 
      ((Action)(() => { })).Time(); 

      (() => { })).Time(); // no way to know what type this should be coerced to 

     }   
    } 

は、今すぐあなたの方法は、多くの異なる種類としてキャプチャすることができます。

+0

質問を考える時間はありがたいですが、答えは答えられません。拡張クラスでDelとDel2を作る理由は何ですか? – smdrager

+0

ポイントは、メソッドをキャプチャすることができるタイプだけです...あなたが好きなだけ多くのメソッドを作ることができます。拡張メソッドは型に対して機能します。方法 - >タイプからの直接的なパスはありません。メソッドはさまざまなタイプで取得できます。 –

+0

あなたの例では、言語がメソッドをあなたの正確な型に強制したいと思っていますが、メソッドが潜在的に多くの型があります。 –

関連する問題