关于c#:非平凡数据类型的预定义常量

pre-defined constants for non-trivial data types

我的目标:为既有ID又有消息的预定义错误创建一个C类。以下是我的尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyError
{
    public static readonly MyError OK = new MyError(0,"OK");
    public static readonly MyError Bad = new MyError(1,"Bad Stuff");

    public MyError(int id, string message)
    {
        this.Id = id;
        this.Message = message;
    }

    public readonly int Id;
    public readonly string Message;
}

这本书汇编得很好,我相信它在实践中会很好地发挥作用。但我总是喜欢遵循代码分析准则。在上述情况下,违反了CA2104"不要声明只读可变引用类型"

我尝试了很多其他方法,包括尝试const而不是readonly(甚至不编译)、get;private set;用于成员访问、struct而不是类等。

哪个是可变类型?身份证还是留言?

我愿意接受任何实现我想要的功能的建议:为非琐碎的数据类型预先定义常量。

当然,我可以忽略这个警告,但我发现这通常是有原因的。

*澄清*我的问题实际上不是关于这个特定的myError类,而是关于为基本数据类型以外的东西定义常量的更基本的问题。

假设我要定义三个双精度常量。让我这样做:

1
2
3
   public const double HighValue = 11.0;
   public const double LowValue = 0.1;
   public const double MidValue = 5.5;

C为我们预先定义的双重常量创建少量有用的常量:NaN、MinValue、MaxValue、NegativeInfinity、PositiveInfinity。

那么现在,如果我想为空间中的三维向量(x,y,z)预先定义一些有趣的常数呢?我可以为双精度数、整数、字符串等定义常量,但是如何为一些不那么简单的东西定义常量呢?原点是一个有趣的常量,我想给它起个名字:

1
2
3
4
5
6
7
8
9
public class Vector3D
{
    /// The problem is that this does not work
    public const Vector3D Origin = { 0.0, 0.0, 0.0 };

    public double X;
    public double Y;
    public double Z;
}

我不需要上千个常量。只有一些像我们的朋友Double和Nan等。班级也不需要特别保护或密封。任何人都可以自由地创建vector3d对象并以任何方式从中派生。我只想有一个特殊的常量名为origin,它有值(0.0,0.0,0.0)


类型不可变。代码分析会被公共只读字段混淆。

您可以通过使公共字段成为公共属性来解决代码分析问题:

1
2
3
4
5
6
7
8
9
public MyError(int id, string message)
{
    this.id = id;
    this.message = message;
}
private readonly int id;
private readonly string message;
public int Id { get { return id; } }
public string Message { get { return message; } }

您的类型不是可变的,但代码分析不知道这一点。这个警告是一个误报;您应该抑制它。

要回答您编辑的问题:

const只能应用于原语。对于自定义类型,static readonly是唯一的选项。

只要类型是正确不变的,它就可以完美地工作。


您的属性不应该是静态的,因为此类的每个实例都有自己的ID和消息,您同意吗?


我会创建一个类

  • 是密封的,以防止它被继承
  • 有一个私有构造函数,以防止从类外部实例化它
  • 为属性提供私有setter,因此不能从外部设置它们。

这将为您提供以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public sealed class MyError
{
    public static readonly MyError OK = new MyError(0,"OK");

    public static readonly MyError Bad = new MyError(1,"Bad Stuff");

    private MyError(int id, string message)
    {
        this.ID = id;
        this.Message = message;
    }

    public int ID { get; private set; }

    public string Message { get; private set; }
}