Question

In C#, I want to make "smart" enums, kind of like is possible in Java, where there's more information attached to an enum value than just the underlying int. I happened upon a scheme of making a class (instead of an enum), as in the following simple example:

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;
        }
    }
}

But when I run Visual Studio's "Code Analyzer" on that, it gives me warning C2104, "Do not declare read only mutable reference types".

I get why you generally wouldn't want to declare read only mutable reference types, but... my class is not mutable, is it?

Reading the docs for the warning, it seems like they're just kind of assuming that any read only reference type is mutable. For example, it says that if the type really is immutable, then feel free to suppress this warning. And in fact it gives me the same warning for the following even simpler class:

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

    private C()
    {
    }
}

So, OK, unless I'm seriously misunderstanding mutability, CA2104 doesn't understand it. And its recommendation is for me to suppress the warning for each line where it comes up, as long as I'm sure the class is really immutable. But:

(1) So unless I turn this check off entirely, I have to suppress it every single time I ever use an immutable read only member, which I might do HUNDREDS of times for any given enumeration?

(2) But worse, even if I do that, then someone can later accidentally introduce mutability, but someone else will still have the false sense of security given by the fact that someone manually put the suppression there saying "I checked and this is immutable"?

Was it helpful?

Solution

You are correct - this is a false positive in this scenario. Your only choices are to suppress individually or turn off the warning, and the downsides are exactly as you described for each option.

Other options to avoid this warning include:

  • Don't use static fields. Instead, you could use a static property with a public get and private set, and initialize in the constructor instead of inline.

  • Make these immutable value types, which will bypass the warning, but potentially give different behavior in some scenarios. This may or may not be an option in your case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top