3

我的目标:为同时具有 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; 私人套装;} 用于成员访问、结构而不是类等。

哪个是可变类型?身份证还是短信?

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

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

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

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

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

C#为我们预定义了一些有用的双常量: NaNMinValueMaxValueNegativeInfinityPositiveInfinity

那么现在,如果想为空间中的三维向量 (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;
}

我不需要成千上万的常量。就像我们的朋友doubleNaN等一样。这个类也不需要特别保护或密封。任何人都可以自由地创建 Vector3D 对象并以他们想要的任何方式从中派生。我只想有一个名为 Origin 的特殊常量,其值为 (0.0, 0.0, 0.0)

4

4 回答 4

3

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


要回答您编辑的问题:

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

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

于 2013-03-25T17:43:35.793 回答
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; } }
于 2013-03-25T17:49:20.307 回答
1

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

于 2013-03-25T18:20:23.080 回答
0

我会创建一个类

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

这将为您提供以下代码:

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; }
}
于 2013-03-25T17:53:45.023 回答