2017-06-15 90 views
1

我想這樣做,但這是不可能的(不能從'void'轉換爲'System.Action')。發送靜態方法+參數作爲參數

class Program 
{ 
    public static void Main() 
    { 
     int n = 2; 
     ClassB cb = new ClassB(); 

     cb.SetMethod(ClassA.MethodA(n)); //Cann't convert 'void' to 'System.Action<int>' 

    } 
} 

public class ClassA 
{ 
    public static void MethodA(int a) 
    { 
     //code 
    } 
} 

public class ClassB 
{ 
    Delegate del; 
    public void SetMethod(Action<int> action) 
    { 
     del = new Delegate(action); 
    } 
    public void ButtonClick() 
    { 
     del.Invoke(); 
    } 
} 
public delegate void Delegate(int n); 

我可以發送參數「N」,如在「使用setMethod」方法第二個參數,但我將不得不存儲變量到後傳遞給「del.Invoke(PARAM)」。我想使用「del.Invoke()」。

+0

使用setMethod有一個動作的參數了methodA返回無效參數,所以你必須要改變的返回類型methodA to Action

+0

@StuartLC即使此代碼仍然不能工作,「ClassB.ButtonClick」方法正在調用單個參數動作的調用,但不提供參數。這有點不清楚他們想要在這裏實現什麼......也許他們只是想要一個沒有參數的Action:'setMethod((=)=> classA.methodA(n)'你提到了嗎? – Clint

+0

請遵循C#的命名規則,這些細節使得你的代碼不可讀。信 –

回答

2

您似乎對代表有誤解。代表代表方法,而不是方法調用。如果您爲方法提供參數,則它會成爲方法調用。所以在這裏:

cb.setMethod(ClassA.methodA(n)); 

ClassA.methodA(n)是一個方法調用,你不能將它分配給委託。

基本上,在這個階段你不能傳遞參數。您在調用委託時必須傳遞參數。例如

del.Invoke(5); 

但是你說你想總是寫del.Invoke(),沒有參數。那麼,那麼你不應該使用Action<int>,你應該只使用Action,它不接受任何參數。

class Program 
{ 
    public static void Main() 
    { 
     int n = 2; 
     ClassB cb = new ClassB(); 

     cb.setMethod(() => ClassA.methodA(n)); 

    } 
} 

public class ClassA 
{ 
    public static void methodA(int a) 
    { 
     //code 
    } 
} 

public class ClassB 
{ 
    Delegate del; 
    public void setMethod(Action action) 
    { 
     del = new Delegate(action); 
    } 
    public void ButtonClick() 
    { 
     del.Invoke(); 
    } 
} 
public delegate void Delegate(); 
+0

這很好,也許我對代表有誤解,你認爲這是一種不好的做法嗎?你可以推薦其他方式或類來做類似的事嗎? – eag845

+0

@ eag845很難說這是否是不好的做法如果你認爲我的答案回答你的問題,請考慮通過點擊那個選中標記來接受它! – Sweeper

0

cb.setMethod(new Action(ClassA.methodA));

0

是否要捕捉在調用點整數目前尚不清楚(例如,作爲一個閉合),或者你是否有意傳遞一個參數明確的委託。

這裏是前一種情況,當值被捕獲:

public static void Main() 
{ 
    var n = 2; 
    var cb = new ClassB(); 
    cb.setMethod(() => ClassA.methodA(n)); 
} 

委託因而不知道捕獲的變量,而只是定義爲:

public delegate void Delegate(); 

然而,如果你不打算在int調用時傳遞int,那麼int的值需要在ButtonClick中傳遞:

public static void Main() 
{ 
    var cb = new ClassB(); 
    cb.setMethod(ClassA.methodA); 
} 
public class ClassB 
{ 
    Delegate del; 
    public void setMethod(Action<int> action) 
    { 
     del = new Delegate(action); 
    } 
    public void ButtonClick() 
    { 
     var n = 2; 
     del.Invoke(n); 
    } 
} 
public delegate void Delegate(int n); 

編輯 - 你認爲還有更好的辦法

沒有真正的理由明確要求委託。 ActionFunc(和Action<int>,取決於以上)are already delegates。作爲一種改進,您應該在調用之前檢查該操作是否已分配。無效條件運算符將將其簡化爲_action?.Invoke()。但是你可以更進一步,並要求其在構造防止行動從以往未賦值:

public class ClassB 
{ 
    // Can be readonly if it is assigned only ever once, in the ctor. 
    private readonly Action _action; 

    public ClassB(Action action) 
    { 
     Contract.Assert(action != null); 
     _action = action; 
    } 

    public void ButtonClick() 
    { 
     _action(); // i.e. no need for Invoke or null check. 
    } 
} 
+0

'cb.setMethod(()=> ClassA.methodA(n))'Works罰款=)。在你寫的最後一個例子中,我想我也不需要委託。但就我而言,你認爲還有更好的方法嗎? – eag845

+0

是的,它捕獲'n'的值,就像設置'setMethod'訂閱時一樣。我已經添加了一些關於提高'ClassB'安全性的小想法。 – StuartLC