2016-11-23 9 views
0

私はXamarinを使ってC#でプロジェクトをやっています。コンパイラは "非同期メソッド 'HandleWidget_ClickButton'がvoidを返すべきではないことを警告します。ここに例を示します:「非同期メソッドはvoidを返さない」というコードをリファクタリングすることはできますか?

//Code is simplified 

public class Widget { 
    public event Action<int> ClickButton; 

    private void FireClickButton (int id) 
    { 
     if (ClickButton != null) { 
      ClickButton (id); 
     } 
    } 

    //somewhere else i call FireClickButton(1); 
} 

public class MyFragment { 
    private _widget Widget; 

    public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     //... 
     _widget = view.FindViewById<Widget> (Resource.Id.widget); 
     //... 
    } 


    public override void OnResume() 
    { 
     base.OnResume(); 
     _widget.ClickButton += HandleWidget_ClickButton; 
    } 

    async void HandleWidget_ClickButton (int id) 
    { 
     await SaveSomethingInStorage (id); 
    } 
} 

何かイベント/アクション/デリゲートに何かを返すことはできますか?これが可能かどうか、あるいは構文を書く方法を文法上分かりませんし、私はかなりの時間をかけて解決策を探しました。他の場所では、イベントを処理するときにasync void(async Taskのようなもの)の代わりにasync voidを使用しても問題ありませんが、#Pragma命令を使用して警告を避け、非表示にしたくないと読んでいます。 @hvdから(解答付き)

EDIT

あなたはイベントハンドラを作成していますが、イベントハンドラ用の.NET の規則に従っていません。あなたがすべき。この警告は、イベントハンドラとして検出できるものについて自動的に抑制された です。

イベントハンドラの.NET規則では、タイプ オブジェクトの送信者、EventArgsタイプのイベント引数、またはEventArgsから派生したクラス が必要です。この署名を使用する場合は、もはや の警告が表示されなくなります。あなたがいるEventArgsから派生しなければなりません

public class MyEventArgs : EventArgs 
{ 
    public MyEventArgs (int id) 
    { 
     ID = id; 
    } 

    public int ID; 
} 

public class Widget { 
    public event EventHandler<MyEventArgs> ClickTest; 

    void FireClickButton (int id) 
    { 
     if (ClickTest != null) { 
      ClickTest (this, new MyEventArgs (id)); 
     } 
    } 
} 

//In observer class 
_widget.ClickTest += HandleWidget_ClickTest; 

async void HandleWidget_ClickTest (object sender, MyEventArgs e) 
{ 
    await DoSomethingAsync (e.ID); 
} 

注:

は、私はこのような私のコードを書き直しました。このようにすると、警告は表示されません。

public event EventHandler<int> AnotherClickTest; 

if (AnotherClickTest != null) { 
    AnotherClickTest (this, 1); 
} 
+2

代わりに 'タスク'を返すことができます。しかし、イベントハンドラはそのルールの例外です - https://msdn.microsoft.com/en-us/magazine/jj991977.aspx – smoksnes

+0

また、この質問を見てください - http://stackoverflow.com/questions/27282617/is-it-safe-as-as-wait-in-asp-net-event-handlers – smoksnes

答えて

2

あなたは、イベントハンドラを作成していますが、「ドンイベントハンドラの.NET規則に従ってください。あなたがすべき。この警告は、イベントハンドラとして検出できるものについて自動的に抑制されます。

イベントハンドラの.NET規則では、タイプobjectの送信者と、タイプEventArgsのイベント引数またはEventArgsから派生したクラスが必要です。この署名を使用すると、警告が表示されなくなります。

+0

実際、VS2015ではこれに関する警告は一切出ません。 – smoksnes

+0

@smoksnesです。 VSには複数の拡張機能があり、追加の警告が表示されます。これらの警告の1つから来ている可能性があります。私はそれがどこから来ているのかを確認します。 – hvd

+0

あなたはおそらく正しいでしょう。私はResharper 2016とVisual Studio 2015を使用していますが、ポイントは残っています - 非同期イベントハンドラではvoidを使用できません。 – smoksnes

1

非同期メソッドは常にタスクを返す必要があります。タスクはまだ完了していないアクションを表します。その後、あなたのメソッドが空であるため、完了した結果を得るために、タスクに対してWait()を実行できます。あなたは待つことはありません。署名は次のようになります。

async Task HandleWidget_ClickButton (int id) 

あなたが何かを返したい場合、それはこのようになります(たとえば、int型):

async Task<int> HandleWidget_ClickButton (int id) 
+0

私は理解します。しかし、あなたの提案を使ってコードをリファクタリングすると、自分のイベントをリファクタリングする必要があるという問題に直面しています。その方法はわかりません。例えば、 "async Task HandleWidget_ClickButton(int id)"を使用すると、私がバインドするコード(_widget.ClickButton + = HandleWidget_ClickButton)は私に "Task HandleWidget_ClickButtonの戻り値の型が間違っています"というエラーを返します。 –

関連する問題