“公共结构包含一个或多个将被导出的非公共字段” - 但是没有字段?

Posted

技术标签:

【中文标题】“公共结构包含一个或多个将被导出的非公共字段” - 但是没有字段?【英文标题】:"The public struct contains one or more non-public fields that will be exported" - but there are no fields? 【发布时间】:2019-09-06 19:43:28 【问题描述】:

我有下面的结构,它正在为 COM 互操作编译。我收到以下构建警告:

warning : 类型库导出器警告处理 'MyNamespace.MyStruct.k__BackingField, 我的程序集名称'。 警告:公共结构包含一个 或更多将被导出的非公开字段

但我看不出它指的是什么 - 根本没有非公共字段或字段。也许编译器正在生成我看不到的东西?这个警告是什么意思,如果我能做些什么来清理它?

这是正在构建的(稍微清理过的)代码:

[Guid("....")]
[ComVisible(true)]
public struct MyStruct

    public string StringA  get; set; 
    public string StringB  get; set; 

    public MyStruct(string a, string b)
    
        StringA = a;
        StringB = b;
    

    public MyStruct(MyStruct other)
    
        StringA = other.StringA;
        StringB = other.StringB;
    

    public override bool Equals(object obj)
    
        if (!(obj is MyStruct)) return false;
        var other = (MyStruct)obj;
        return
            other.StringA == this.StringA &&
            other.StringB == this.StringB;
    

    public static bool operator ==(MyStructa, MyStructb) => a != null && a.Equals(b);
    public static bool operator !=(MyStructa, MyStructb) => !(a == b);
    public override int GetHashCode() => ToString().GetHashCode();

    public override string ToString() => $"StringA-StringB";

这里是生成的 IDL:

typedef [uuid(....), version(1.0), custom(xxxx, MyNamespace.MyStruct)]
struct tagMyStruct 
    LPSTR <StringA>k__BackingField;
    LPSTR <StringB>k__BackingField;
 MyStruct;

由 OleView 生成。我可以看到它包含与警告中相同的 k__BackingField - 但不清楚这意味着什么。

【问题讨论】:

【参考方案1】:

您正在使用自动属性:

public string StringA  get; set; 

编译器会为它们中的每一个自动生成一个支持字段。这正是

MyNamespace.MyStruct.k__BackingField

指的是。


您收到警告是因为暴露私有字段可能是无意的,或者可能会导致安全问题。由开发人员来验证是否是这种情况。在您的具体示例中,不会违反封装,因此可以忽略警告或禁止警告。另请参阅MSDN 的官方文档:

何时禁止显示警告

如果可以接受该场的公开暴露,则可以安全地取消此规则的警告。

【讨论】:

但是为什么会发出警告呢?说明什么问题? @DaveInCaz:考虑一个具有私有字段accountNumber 的类BankAccount,然后将其导出。 COM 互操作客户端现在可以读取该类的作者可能打算私有的字段因为它是一个秘密。该警告告诉您,您需要了解这种情况并考虑一下。在您的情况下,您有一个私有字段,该字段仅存在于公共 getter/setter 之上,因此没有问题。这确实是警告生成中的一个缺陷,因为它可能足够聪明地注意到有一个公共 getter/setter 对。 @EricLippert 谢谢,我觉得这是 TLBEXP 在其警告中过于激进,或者缺乏细微差别,无法看出这种(可能很常见)情况不是问题。您的最后一条评论似乎支持了这一点。

以上是关于“公共结构包含一个或多个将被导出的非公共字段” - 但是没有字段?的主要内容,如果未能解决你的问题,请参考以下文章