非平凡数据类型的预定义常量

时间:2013-03-25 17:42:42

标签: c# const readonly mutable

我的目标:为具有ID和消息的预定义错误创建C#类。 这是我试过的:

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;私人集;用于成员访问,struct而不是类等。

哪种类型可变?我还是留言?

我愿意接受任何能够实现我想要的建议:非平凡数据类型的预定义常量。

当然,我总是可以忽略警告,但我发现通常有这样的理由。

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

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

   public const double HighValue = 11.0;
   public const double LowValue = 0.1;
   public const double MidValue = 5.5;

C#为我们预先定义的 double 创建了少量有用的常量: NaN MinValue MaxValue NegativeInfinity PositiveInfinity

现在,如果 I 想要在空间中为三维向量(X,Y,Z)预先定义一些有趣的常量,该怎么办?我可以为双精度,整数,字符串等定义常量,但是如何为不那么微不足道的东西定义常量呢? Origin是一个有趣的常数,我想给它起一个名字:

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)

4 个答案:

答案 0 :(得分:2)

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


回答您编辑过的问题:

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

只要类型是正确不可变的,它就能完美地运行。

答案 1 :(得分:2)

类型不可变。公共只读字段使代码分析变得混乱。

您可以通过将公共字段设为公共属性来修复代码分析问题:

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

我会创建一个

的类
  • 密封,以防止其被继承
  • 有一个私有构造函数,以防止它从类外部实例化
  • 使用私人设定者提供属性,因此无法从外部进行设置。

这会给你以下代码:

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