我正在使用Xamarin在c#中做一个项目。编译器警告我"异步方法' HandleWidget_ClickButton'不应该返回无效"。见这里的例子:
//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那样),但我喜欢避免警告而不喜欢使用#Pragma指令隐藏它们。
来自@hvd的编辑(有答案):
您创建了一个事件处理程序,但您没有遵循.NET 事件处理程序的约定。你应该。警告是 自动抑制可以检测为事件处理程序的内容。
事件处理程序的.NET约定需要类型的发件人 对象和事件参数,类型为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);
}
请注意,您必须从EventArgs派生。这样做不会抑制警告:
public event EventHandler<int> AnotherClickTest;
if (AnotherClickTest != null) {
AnotherClickTest (this, 1);
}
答案 0 :(得分:2)
您创建了一个事件处理程序,但您没有遵循事件处理程序的.NET约定。你应该。对于可以检测为事件处理程序的内容,将自动禁止警告。
事件处理程序的.NET约定要求类型为object
的发件人和类型为EventArgs
的事件参数或源自EventArgs
的类。如果您使用此签名,则不应再收到警告。
答案 1 :(得分:1)
异步方法总是应该返回一个Task。任务表示尚未完成的操作。之后你可以对任务执行Wait(),以获得完成的结果......因为你的方法是Void,你不会做任何等待。签名应如下所示:
async Task HandleWidget_ClickButton (int id)
如果你想要返回一些东西,就像这样(例如,int):
async Task<int> HandleWidget_ClickButton (int id)
答案 2 :(得分:0)
如其他答案中所述,您可以正确构造事件处理程序,以免引发事件处理程序,因为运行时将知道如何正确调用委托。这是一些代码,向您展示如何构建它:
向您的视图公开一个公共命令
public ICommand CopyDeviceId { get; private set; }
然后,使用委托创建命令实例
CopyDeviceId = new Command(() => CopyDeviceIdValue(this, EventArgs.Empty));
最后,创建异步委托
private async void CopyDeviceIdValue(object sender, EventArgs e)
{
\\code here
}