gpt4 book ai didi

c# - 使用约束定义/引发通用事件

转载 作者:行者123 更新时间:2023-12-04 08:02:42 24 4
gpt4 key购买 nike

我想引发一个允许类型为 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: Argument 2: cannot convert from 'WidgetRequiredEventArgs<T>' to 'WidgetRequiredEventArgs<Widget>'


e论点就行:
this.WidgetRequired(this, e);
那么为什么不限制 OnWidgetRequired<T>()WidgetRequiredEventArgs<T>满足事件处理程序的类型定义,我怎样才能编译它?

最佳答案

您的示例中有一个基本问题。您希望事件的订阅者能够生成您在泛型方法中指定的对象类型。 IE。您的方法创建 args 对象,处理程序设置属性,方法引发属性,然后方法获取属性值。
但是,如果您可以按照您的要求做,那么生产者可以设置任何类型的 Widget它们旨在处理,即使它不是 Widget 的类型正在调用该方法进行检索。
或者换句话说,属性的泛型类型不能是变体,因为只有协变或逆变是合法的,不能同时是两者。
一种方法是将事件本身移动到泛型类型中,而不是使用泛型方法。这允许在每一步都使用正确的类型声明事件。该框架将为代码中使用的每个泛型类型参数实例化一个具有单独事件的新具体类型。
例如,这是一个简单的通用实现(我将类名从 Widget 重命名为更具可读性的内容,因此类型之间的关系更加清晰,并且为了简单起见,我将所有内容都做了 static...当然,如果您有一个场景,其中使用相同的泛型类型参数有多个事件是有意义的,则可以使这些非静态):

class Base { }
class Derived1 : Base { }
class Derived2 : Base { }

class BaseEventArgs<T> : EventArgs where T : Base
{
public T Item { get; set; }
}

static class ItemHandler<T> where T : Base
{
public static event EventHandler<BaseEventArgs<T>> ItemProducer;

public static T OnBaseRequired()
{
BaseEventArgs<T> args = new BaseEventArgs<T>();

ItemProducer?.Invoke(null, args);

return args.Item;
}
}
然后你只需像这样使用它:
public void DoSomethingThatNeedsABase<T>() where T : Base
{
Base widget = ItemHandler<T>.OnBaseRequired();

//...now do something with the "Base", aka "widget
}

关于c# - 使用约束定义/引发通用事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66375080/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com