c++/cli 假设控制类型的控制循环

c++/cli Control loop with assumption of control type

我想访问 Controls 组中的所有用户控件。我正在使用以下循环:

std::vector<LaminaClass> Laminae;

for each(Control ^E in Controls)
{
    if (E->GetType() == ClassLibrary1::Lamina_Input1::typeid)
    {
        // Create a new lamina class object by copying the current lamina control handle
        LaminaClass newLam(E);

        // Put the lamina in the appropriate location in the Laminae vector:
        Laminae.push_back(newLam);
    }
}

问题是,即使我用 if 语句过滤了控件,我仍然不能假设控件 EClassLibrary1::Lamina_Input1 类型,这意味着我可以'不要做任何特定于该控件类型的事情 to/with 它。我可以做一般的控制事情,但不能做任何 Lamina_Input1 控件独有的事情。

我也试过这个:

std::vector<LaminaClass> Laminae;

    // For each lamina control in the group of controls:
for each(ClassLibrary1::Lamina_Input1 ^LamContr in Controls)
{
    // Create a new lamina class object by copying the current lamina control handel
    LaminaClass newLam(LamContr);

    // Put the lamina in the appropriate location in the Laminae vector:
    Laminae.push_back(newLam);
}

在这种情况下,我收到以下错误:

在调试器中:

我已经坚持了一段时间了。我花了很多时间试图查找答案但没有成功(可能是由于我无法以简洁的方式准确描述问题)。

标准警告:虽然可以使用 C++/CLI 编写应用程序的主体,甚至可以使用 WinForms 在 C++/CLI 中编写 GUI,但不推荐这样做。 C++/CLI 适用于互操作场景:在 C# 或其他 .Net 代码需要与非托管 C++ 交互的情况下,C++/CLI 可以提供两者之间的转换。对于初级开发,如果需要托管代码,建议使用 C# 和 WinForms 或 WPF,如果需要非托管代码,建议使用 C++ 和 MFC。


您是否正在寻找合适类型的转换?

LaminaClass newLam(dynamic_cast<Lamina_Input1^>(E));
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

即使你检查 E 是你期望的类型,这不会改变 E 的类型,你仍然必须转换它。

for each 循环中指定一个子类是有效的,但它会对列表中的每个对象执行 static_cast 到该类型,如您所见,这将引发异常如果演员阵容无效。

在 C++/CLI 中执行此操作的最简洁方法是利用上下文转换为 bool,也就是说,使用句柄类型作为条件表达式自动成为与 nullptr 的比较.

例如:

for each(Control ^E in Controls)
{
    if (auto LI = dynamic_cast<ClassLibrary1::Lamina_Input1^>(E))
    {
        LaminaClass newLam(LI);

        // ...
    }
}

对于熟悉 C# 的人来说,这相当于使用 as 关键字,例如

foreach (Control E in Controls)
{
    var LI = E as Lamina_Input;
    if (LI != null)
    {
        new LaminaClass(LI) // ...
    }
}

只是作用域只是 if 语句本身。在 C# 7 中终于有了一个真正的等价物:

foreach (Control E in Controls)
{
    if (E is Lamina_Input LI)
    {
        new LaminaClass(LI) // ...
    }
}