【问题标题】:C# - Mark Variable As Const (Readonly)C# - 将变量标记为常量(只读)
【发布时间】:2013-06-05 13:23:34
【问题描述】:

我的一些全局变量只需要启动一次。我通过加载文件并将它们设置为任何内容来做到这一点。现在我想当我尝试为这个变量设置一个新值时抛出一个异常。

public class Foo
{
    public static int MIN;

    private static loadConstants()
    {
        MIN = 18;
    }

    public static void Main()
    {
        loadConstants();
        MIN = 15; // this must throw an exception
        // edit: at least mustn't set the new value
    }
}

我该怎么做?

(可能很简单,对不起)

【问题讨论】:

  • "this must throw an exception" -- 你真的需要它来编译,直到运行时才失败?到目前为止,您得到的答案确保 MIN = 15; 行甚至不会编译,因此它也不会引发异常。
  • TS 可能并不是字面上的意思是他想要一行抛出异常,只是该行不会将常量 MIN 设置为一个值。
  • 是的,不需要例外。只有唯一的值必须在运行时保持。
  • readonly 就是这个意思。该值只能在构造函数中设置,之后为常量。

标签: c# variables constants readonly


【解决方案1】:

创建一个静态构造函数,并将变量标记为只读。然后在构造函数中设置值。

public static class Foo
{
    public static readonly int MIN;

    static Foo()
    {
        MIN = 18;
    }

    public static void Main()
    {

    }
}

【讨论】:

  • 好的,我也尝试用反射破解变量。我可以设置一个新值。可以在不使变量的单行声明复杂化的情况下以某种方式避免这种情况吗?
【解决方案2】:
public class Foo
{
    public readonly static int MIN;

    static Foo()
    {
        MIN = 18;
    }

    public static void Main()
    {
    }
}

【讨论】:

  • 如果你尝试修改它,这比在运行时抛出异常要好得多。这样做意味着编译器不会你在静态ctor中修改它。
  • OP提到的,他其实是在“加载文件”而不是简单的MIN = 18。我强烈建议不要在静态类型构造函数中执行任何文件 I/O。或者任何复杂的逻辑。在调试时使用它们真的很痛苦,而且很难控制它们执行的确切时间。
  • @Imi 是的,我知道,我已经结束了。谢谢!
【解决方案3】:

如果您不能或不想使用其他答案中的静态构造函数(例如,因为在实际初始化变量之前您有很多与类型有关的事情,或者因为您意识到静态构造函数是调试真的很痛苦..)你可以做其他事情:


一种编译时解决方案是将您自己类型中的变量打包为非静态只读,并持有对该类型的静态引用

public class Constants
{
    public readonly int MIN;
    public Constants() { MIN = 18; }
}
public class Foo
{
    public static Constants GlobalConstants { get; private set; }

    public static void Main()
    {
        // do lots of stuff
        GlobalConstants = new GlobalConstants();
    }
}

或者你可以将常量变成一个属性,只为你班级之外的任何人提供 getter。请注意,声明类仍然可以更改属性。

public class Foo
{
    public static int MIN { get; private set; } }

    public static void Main()
    {
        MIN = 18;
        MIN = 23; // this will still work :(
    }
}

或者 - 如果出于某种奇怪的原因 - 你真的想要一个异常而不是编译错误,你可以从常量中创建一个属性并在 setter 中抛出你的异常。

public class Foo
{
    static int _min;
    public static int MIN { get { return _min; } set { throw new NotSupportedException(); } }

    public static void Main()
    {
        _min = 18;
    }
}

【讨论】:

    【解决方案4】:

    您可以创建一个公共属性,而不是拥有一个公共成员变量,然后在您的实现中管理您的 CONST 逻辑。

     private static int? _min;
    
     public static int MIN
     {
        set { 
                if (!_min.HasValue())
                {
                    _min = value;
                }
                else
                {
                   throw;
                }
        }
    
        get {
               return _min.ValueOrDefault();
        }
    
     }
    

    【讨论】:

    • 这在我的应用程序中会很重,因为我有大约 100 个。
    猜你喜欢
    • 2015-04-09
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-18
    • 2020-10-31
    • 2015-08-29
    相关资源
    最近更新 更多