C#可变性 - VS Code分析给我CA2104提示?看起来...不太好。我是否理解有误?

7

在C#中,我想要创建“智能”枚举,就像Java中可能的那样,其中一个枚举值附加了比基础int类型更多的信息。我偶然发现了一种制作类(而不是枚举)的方法,例如以下简单示例:

public sealed class C
{
    public static readonly C C1 = new C(0, 1);
    public static readonly C C2 = new C(2, 3);

    private readonly int x;
    private readonly int y;

    private C(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int X
    {
        get
        {
            return this.x;
        }
    }

    public int Y
    {
        get
        {
            return this.y;
        }
    }
}

然而,当我在Visual Studio上运行“代码分析器”时,它会给出警告C2104,“不要声明只读的可变引用类型”。

我知道你通常不想声明只读的可变引用类型,但是……我的类不可变,对吧?

阅读警告文档,似乎它们只是假设任何只读引用类型都是可变的。例如,它说如果类型确实是不可变的,则可以随意禁止此警告。 实际上,即使是下面更简单的类,它也会给我同样的警告:

public sealed class C
{
    public static readonly C C1 = new C();
    public static readonly C C2 = new C();

    private C()
    {
    }
}

好的,除非我严重误解可变性,否则CA2104无法理解它。其建议是只要我确定该类确实是不可变的,在每个出现警告的行上都抑制警告。但是:

(1) 那么,除非我完全关闭此检查,否则每次使用不可变的只读成员时,我都必须抑制它,而我可能会为任何给定的枚举使用数百次?

(2) 更糟糕的是,即使我这样做了,然后有人可以意外地引入可变性,但其他人仍然会被手动放置抑制警告所带来的虚假安全感所迷惑,“我检查过这是不可变的”?


我有一个类似的问题:https://dev59.com/l2Uo5IYBdhLWcg3w1yPH - Matthew Watson
1个回答

5
您说得对 - 在这种情况下,这是一个错误的检测结果。您唯一的选择是逐个抑制或关闭警告,并且每个选项的缺点正如您所描述的那样。
避免此警告的其他选项包括:
- 不要使用静态字段。相反,您可以使用具有公共 get 和私有 set 的静态属性,在构造函数中初始化而不是内联。 - 将这些变量定义为不可变值类型,将规避警告,但在某些情况下可能导致不同的行为。这可能是您的情况的一个选项或不是。

将其更改为值类型确实有效 - 谢谢!我认为这样使用应该没问题,所以我会开始这样做,并在遇到其他问题时处理它们。再次感谢! - user2350774
@user2350774,使用属性是我的首选。公共字段有很多缺点(你可以在这里搜索大量理由来避免在公共API中使用字段)。 - Reed Copsey
我不确定我理解了这个 - 我确实使用了X和Y的属性。或者您是在建议我也应该为我想要处理的静态内容使用属性,本质上就像枚举值一样? - user2350774
@user2350774 是的 - 将C1/C2(你的“enums”)作为属性而不是字段,警告就会消失。 - Reed Copsey
太好了 - 这样更好。再次感谢! - user2350774

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接