更简洁优雅的 VARIANT 类型使用方式

Posted

技术标签:

【中文标题】更简洁优雅的 VARIANT 类型使用方式【英文标题】:more concise and elegant way of using VARIANT type 【发布时间】:2013-10-11 19:27:15 【问题描述】:

以下代码来自 MSDN 源代码示例,我有一个问题。

为什么我们需要使用多个VARIANT result; 定义来定义不同的变量?我们能否以更短的方式初始化不同类型(主要是整数和字符串)的VARIANT 变量?简洁安全的方法。

另外,可以将VariantInit(&result) 替换为result.vt = VT_EMPTY 以将VARIANT 标记为空吗?

int main()

    //blahblahbla
    
        VARIANT x;
        x.vt = VT_R4;   // 4-byte real. 
        x.fltVal = 1.2f;
        wprintf(L"Set FloatProperty = %.2f\n", x.fltVal);
        hr = AutoWrap(DISPATCH_PROPERTYPUT, NULL, pSimpleObj, L"FloatProperty", 1, x);
    
    
        VARIANT result;
        VariantInit(&result);
        hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pSimpleObj, L"FloatProperty", 0);
        wprintf(L"Get FloatProperty = %.2f\n", result.fltVal);
    

    
        VARIANT result;
        VariantInit(&result);
        hr = AutoWrap(DISPATCH_METHOD, &result, pSimpleObj, L"HelloWorld", 0);
        wprintf(L"Call HelloWorld => %s\n", result.bstrVal);
        VariantClear(&result);
    

【问题讨论】:

【参考方案1】:

为什么我们需要使用不同的“VARIANT result”变量?

您不必这样做,这只是示例的编写方式。重用 VARIANT 变量时要小心,仅调用 VariantInit() 或分配 result.vt = VT_EMPTY 是危险的。变体可以存储需要释放的资源。正如在 sn-p 中所做的那样,请注意释放 BSTR 所需的对 VariantClear() 的调用。与 VariantInit() 不同的是,VariantClear 在再次初始化变体之前首先释放资源。

还要注意在 DISPATCH_PROPERTYGET 调用之后它是如何被省略的。没关系,但你必须知道你在做什么。在这种情况下可以,因为 VARIANT 可以存储浮点值而无需为其分配内存。无论如何调用 VariantClear() 肯定没有错。

请记住,MSDN 源代码通常是用 C 编译器编写的。如果您编写 COM 代码,那么您几乎总是倾向于使用 C++。哪位肯定能做得更好,现在可以使用_variant_t class。一个包装类,可以避免愚蠢的错误并使语法更清晰,正如您所要求的。您不再需要使用 VariantInit 或 VariantClear,包装器会为您完成它并且永远不会出错。

【讨论】:

【参考方案2】:

直接使用VARIANT 的替代方法是使用C++ 可用的包装类之一。根据您是使用 MFC 还是 ATL 还是仅使用本机 C++,有多种选择。

对于一个简单的包装器,_variant_t 类提供了一些基本便利,尤其是对于简单数据,例如整数和字符串。该类不直接支持SAFEARRAY 类型VARIANTS

请参阅Microsoft Developer Network topic _variant_t Class,它提供了包装类和可用方法的概述。

_variant_t 对象封装了VARIANT 数据类型。班上 管理资源分配和释放并进行函数调用 酌情发送至VariantInitVariantClear

构造函数有多种变体,它们采用不同的参数类型并创建适当类型的VARIANT 对象。对于标准的 Windows API UNICODE 或 wchar_t 字符串,您需要使用 BSTR 对象。

ATL 提供CComVariant,MFC 提供COleVariant 类来包装VARIANT。这三个包装类(_variant_tCComVariantCOleVariant 似乎都派生自 struct tagVARIANTVARIANT 的底层数据结构,因此所有这些似乎都可用于任何使用 @ 的接口987654343@.

来自Microsoft Developer Network CComVariant Class的CComVariant的注释

CComVariant 包装了 VARIANT 和 VARIANTARG 类型,它由一个 union 和一个成员,指示存储在 联盟。 VARIANT 通常用于自动化。

CComVariant 派生自 VARIANT 类型,因此可以在任何地方使用它 可以使用变体。例如,您可以使用 V_VT 宏 提取 CComVariant 的类型,或者您可以访问 vt 成员 就像使用 VARIANT 一样。

还有来自Microsoft Developer Network COleVariant Class 的COleVariant 的注释:

该类派生自 VARIANT 结构。这意味着您可以 在调用 VARIANT 的参数中传递 COleVariant 并且 VARIANT 结构的数据成员是可访问的数据成员 的 COleVariant。

【讨论】:

以上是关于更简洁优雅的 VARIANT 类型使用方式的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot - 使用Assert校验让业务代码更简洁

SpringBoot - 使用Assert校验让业务代码更简洁

有没有更优雅的方法来添加可为空的整数?

自从用了 Stream,代码更简洁优雅了!

相信我,使用 Stream 真的可以让代码更优雅!

相信我,使用 Stream 真的可以让代码更优雅!