.net C++;概括代表

.net C++;概括代表,.net,callback,delegates,c++-cli,.net,Callback,Delegates,C++ Cli,我有一个类似的情况: ref class Manager { delegate void answer1(String^ Message, int Avalue); delegate void answer2(Object^ Obj, double Something); answer1 ^ Callbackfor1; answer2 ^ Callbackfor2; void RegisterCallback1(answer1 ^ Address);

我有一个类似的情况:

ref class Manager
{ 
    delegate void answer1(String^ Message, int Avalue);
    delegate void answer2(Object^ Obj, double Something);

    answer1 ^ Callbackfor1;
    answer2 ^ Callbackfor2;

    void RegisterCallback1(answer1 ^ Address);
    void RegisterCallback2(answer2 ^ Address);
}

我如何才能在更好的解决方案中实现这一点?每次我都必须为每次回调创建一个委托、一个指针和一个过程。有更好的概括方法吗?我认为每次都应该重新创建委托,但我希望避免重新创建过程和指针。

首先,如果您公开
Callbackfor1
Callbackfor2
(我假设您的类成员都是公共的)然后,您也不需要
RegisterCallback1
RegisterCallback2
:它们只是使调用方代码更加冗长的辅助方法:

manager->RegisterCallback1(YourMethod);
而不是:

manager->Callbackfor1 += YourMethod;
但是请注意,将代理公开后,您将完全公开它们,调用方可能会这样写:

manager->Answer1 = nullptr;
那么在我看来,您应该删除helper方法(保持字段公共)或保持helper方法(使字段私有)。还有另一种选择:事件。它们完全是委托,但不允许调用方设置它们(仅在调用列表中添加/删除函数):

请注意,使它们成为事件(或使它们保持私有)也会阻止调用方直接调用它们,您只能从您声明的类中引发事件。谁使用你的班级:

manager->Callback1 += YourMethod;    // Add to invocation list
manager->Callback1 -= YourMethod;    // Remove from invocation list
manager->Callback1 = nullptr;        // Not allowed: it doesn't compile
manager->Callback1(L"some text", 0); // Not allowed: it doesn't compile
关于委托声明和签名:如果您的目标是新的.NET Framework版本,则可以使用
Action
Func
通用委托。像这样:

ref class Manager {
public:
    event Action<String^, int>^ Callback1;
    event Action<Object^, double>^ Callback2;
};
现在更改您的
管理器
类:

ref class Manager {
public:
    event EventHandler<Callback1EventArgs^>^ Callback1;
};
但方法签名不同:

void YourMethod(Object^ sender, Callback1EventArgs^ e) {
    // In case you need it you have a reference to object
    // that generated this "event".
    Manager^ manager = safe_cast<Manager^>(sender);

    // You find all your properties inside event arguments
    Console::WriteLine(L"Message is {0} and value is {1}",
        e->Message, e->Value);
}
将成为:

Callback1(this, gcnew Callback1EventArgs(L"Some message", 0));

这样更好吗?拥有一个类会让你的代码更加冗长,但是当参数改变时它会有很大的帮助:你只需要添加一个属性并重新编译(使用方法参数,你需要找到并更新每个方法寄存器作为
Callback1
的委托,并添加该参数,即使没有使用).

您可以使用操作泛型类型来避免声明自己的委托类型。这是关于如何让它“更好”的问题,您确实需要创建委托对象并提供一个目标方法,这就是委托的工作方式。感谢您的回答,我正在寻找您的所有解决方案,这里有一个问题:事件操作^Callback1;该如何为其分配程序?这样做:委托void answer1(字符串^Message,int-Avalue);事件应答器1^Callbackfor1;我使用:经理cla;cla.Callbackfor1+=gcnew Manager::answer1(MyCall);如果您放弃回答1委托并使用标准的
操作
cla.Callbackfor1+=gcnew操作(…
,如果您保留
answer1
委托,但将
Callbackfor1
delegate
更改为
event
,那么就可以了。在我看来,您应该删除委托,移动到
event
并将其与
Callback1EventArgs
EventHandle^
一起使用(最后一个示例)。
ref class Manager {
public:
    event EventHandler<Callback1EventArgs^>^ Callback1;
};
manager->Callback1 += YourMethod;
void YourMethod(Object^ sender, Callback1EventArgs^ e) {
    // In case you need it you have a reference to object
    // that generated this "event".
    Manager^ manager = safe_cast<Manager^>(sender);

    // You find all your properties inside event arguments
    Console::WriteLine(L"Message is {0} and value is {1}",
        e->Message, e->Value);
}
answer1^ callbackfor1 = Callbackfor1;
if (callbackfor1 != nullptr)
    callbackfor1(L"Some message", 0);
Callback1(this, gcnew Callback1EventArgs(L"Some message", 0));