【问题标题】:Do not declare visible instance fields warning in sequential struct不要在顺序结构中声明可见实例字段警告
【发布时间】:2019-01-28 09:36:26
【问题描述】:

我在wpf 应用程序中使用了一些DllImports 来捕获屏幕。我在user32.dll 中打电话给GetWindowRect。它需要传递给它的 rect 结构。结构的布局很重要,因为它是本机调用。

我正在试用 VS 2019 预览版 2,它给了我以前从未见过的警告。 rect 中的所有字段都会生成相同的警告:

CA1051 Do not declare visible instance fields

在其余代码中,我通过附加 {get;set;} 将字段转换为属性来解决此问题。我不知道我是否可以在布局很重要的结构中安全地做到这一点。

Rect 还警告我应该覆盖 Equals。

CA1815 Rect should override Equals.

CA1815 Rect should override the equality (==) and inequality (!=) operators.

虽然我从不比较它,而且绝对不需要,我只是想修复警告。

public static class NativeMethods
{
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    public static IntPtr _GetForegroundWindow()
    {
        return GetForegroundWindow();
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern IntPtr GetDesktopWindow();

    public static IntPtr _GetDesktopWindow()
    {
        return GetDesktopWindow();
    }

    //Am unable to get code analysis to shut up about this.
    [DllImport("user32.dll")]
    private static extern int GetWindowRect(IntPtr hWnd, ref Rect rect);

    public static IntPtr _GetWindowRect(IntPtr hWnd, ref Rect rect)
    {
        return (IntPtr)GetWindowRect(hWnd, ref rect);
    }        
}

[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}    

如何解决这些警告?

【问题讨论】:

  • 正如我在问题中所说(在代码的其余部分,我通过附加 {get;set;} 将字段转换为属性来解决此问题。我不知道我是否可以在布局很重要的结构中安全地执行此操作。)这就是我通常修复它的方式。这是一种特殊情况,因为它是本机调用中使用的结构。 {get;set;} 将生成一个 getter 和 setter,可能会改变结构的布局。你确定 {get;set;} 是安全的吗?
  • 忽略这种特殊情况下的警告。
  • @Dirk 我知道你可以这样做,而且可能没问题,但我希望有更好的解决方案。
  • 这些是互操作类型,其形状由外部(非 C#)力量决定。你不能保证任何互操作类型都符合良好的 C# 实践,所以我肯定会在这里查看抑制。
  • @IvanStoev 将其标记为内部修复!请添加您的答案,以便我标记它。

标签: c# winapi pinvoke compiler-warnings


【解决方案1】:

CA1051: Do not declare visible instance fields 的文档说:

原因

一个外部可见的类型有一个外部可见的实例字段。

类型和字段的关键点是外部。因此修复(因为这应该只在你的应用程序中使用)是使struct(以及暴露它的类)internal

[StructLayout(LayoutKind.Sequential)]
internal struct Rect
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}    

internal static class NativeMethods
{
    // ...
}

请注意,CA1051 警告不是由 C# 编译器生成,而是由代码分析生成,因此可以从 CA 规则集中排除或忽略(尽管文档建议 not suppress it)。

【讨论】:

    【解决方案2】:

    您可以像这样在文件中隐藏警告:

    #pragma warning disable CA1051, CA1815
    

    或在整个项目的 csproj 文件中禁用它

    <NoWarn>CA1051, CA1815</NoWarn>
    

    编辑如果您想修复警告而不是禁止它,您应该按照警告消息进行操作。

    虽然我从不比较它,而且绝对不需要,我只是想修复警告。

    除非您添加消息中建议的运算符,否则将出现警告。警告意味着“它现在可能对你有用,但不是最佳实践”。覆盖结构的相等运算符提高了可读性和性能,结构也应该是不可变的,公共字段打破了不变性并隐藏了潜在的错误。

    【讨论】:

    • 我知道如何抑制警告,我希望修复警告,而不是抑制它。
    猜你喜欢
    • 2019-12-11
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    相关资源
    最近更新 更多