【问题标题】:Strange behaviour of static readonly variables and collection in C#C# 中静态只读变量和集合的奇怪行为
【发布时间】:2012-07-01 20:31:41
【问题描述】:

我在命名空间 Global 中创建了以下类

namespace Global
{
    public static class Status
    {
        public static readonly char Active;
        public static readonly char Suspended;
        public static readonly char Terminiated;
        public static readonly char Deleted;

        private static readonly Dictionary<char, string> statusCollection;
        public static Dictionary<char, string> StatusCollection 
        { 
            get 
            { 
                return statusCollection; 
            }
        }

        static Status()
        {
            statusCollection = new Dictionary<char, string>();
            statusCollection.Add('A', "Active");
            statusCollection.Add('S', "Suspended");
            statusCollection.Add('T', "Terminated");
            statusCollection.Add('D', "Deleted");

            Active = 'A';
            Suspended = 'S';
            Terminiated = 'T';
            Deleted = 'D';
        }
    }

    public class a
    {
        public void add()
        {
            //How to make this collection readonly
            Status.StatusCollection.Add('N', "asd"); 

            Status.Active = 'M'; //Throws a compile time exception, changes not allowed
        }
    }
}

奇怪的行为当我尝试在即时窗口中更新 Status.Active 时,我预计该值不会改变,但允许更改。这是否意味着我们可以通过反射或运行时更改readonly 变量的值?

【问题讨论】:

  • 顺便说一下,here 是关于 readonly 字段的另一种处理方式,这次是在结构中...

标签: c# oop static readonly


【解决方案1】:

是的,您可以在运行时通过反射更改readonly 属性的值。这是一个非常简单的 POC:

public class Program
{
    private static readonly string Foo = "Bar";

    static void Main()
    {
        typeof(Program)
            .GetField("Foo", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, "new value");
        Console.WriteLine(Foo);
    }
}

当您运行此控制台应用程序时,它将打印:

new value

【讨论】:

  • 在这种情况下它是应用程序的线程吗?这种情况是否也适用于常量。我的信念是我们不能更改常量,因为它们是在编译时设置的,并且每个 dll 都维护自己的副本。这是真的吗?
  • 不,这不适用于常量。它们在编译时在程序集的元数据中烘焙,您无法以任何可能的方式更改它们的值,即使使用反射也不行。至于你的第一个问题,这是否是一个线程,你的意思是threat吗?如果您的意思是威胁,那将视情况而定。
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2018-08-06
  • 2016-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多