【发布时间】:2021-02-25 19:19:59
【问题描述】:
我想引发一个事件,允许返回 Widget(或任何派生类)类型的对象,具体类型通过泛型定义。
public class WidgetProcessor
{
public event EventHandler<WidgetRequiredEventArgs<Widget>> WidgetRequired;
public void DoSomethingThatNeedsAWidget<T>() where T: Widget
{
Widget widget = OnWidgetRequired<T>();
//...now do something with the widget
}
private T OnWidgetRequired<T>() where T: Widget
{
T widget = null;
if (this.WidgetRequired != null)
{
WidgetRequiredEventArgs<T> e = new WidgetRequiredEventArgs<T>();
this.WidgetRequired(this, e);
widget = e.Widget;
}
return widget;
}
}
public class WidgetRequiredEventArgs<T>
: EventArgs where T : Widget
{
public WidgetRequiredEventArgs()
{
}
public T Widget { get; set; }
}
OnWidgetRequired<T>() 和 DoSomethingThatNeedsAWidget<T>() 上的约束允许我将指定类型限制为 Widget 或派生类。理想情况下,我会为事件声明做同样的事情,但它不支持使用 <T> 和对事件参数的约束,所以我必须将其明确声明为 Widget。
但是,这会产生编译时错误:
CS1503:参数 2:无法从 'WidgetRequiredEventArgs
' 转换为 'WidgetRequiredEventArgs '
对于e 参数就行了:
this.WidgetRequired(this, e);
那么为什么OnWidgetRequired<T>() 和WidgetRequiredEventArgs<T> 上的约束不满足事件处理程序的类型定义,我怎样才能让它编译呢?
【问题讨论】:
-
您尝试做的事情是非法的,因为它不安全。您提出的语法将允许任何可以生成任何类型的
Widget的订阅者处理任何类型的Widget的Widget的生成。 IE。即使OnWidgetRequired<T>()的调用者被调用WidgetB,订阅者也可以产生WidgetA。如果您可以调整问题以描述不非法的操作,那么也许可以提供一个很好的答案。否则,这只是我们已经提出的所有其他“我想要的变体类型场景是非法的”问题的重复。 -
WidgetRequired的实际用途是什么?如果此事件有多个订阅者会发生什么? -
@PeterDuniho 看起来你是对的,这只是我们已经拥有的所有其他“我想要的变体类型场景是非法的”问题的重复,但其他人都没有足够清楚地解释为什么我的情况是非法的,因此我的问题。
-
@GuruStron 代码位于 UI 库中,事件实际上只是允许它在不知道/不依赖于它来自何处的情况下请求一个对象。所以在实践中,只有一个订阅者代表正在使用这个库的 UI 环境。