在C#中实现本地运行时不变性

时间:2013-07-26 14:10:09

标签: c# immutability

我目前知道有两种方法可以在C#中使实例不可变:

方法1 - 编译时间不变性

void Foo() 
{
    // Will be serialized as metadata and inserted
    // as a literal. Only valid for compile-time constants
    const int bar = 100;
}

方法2 - 只读字段

class Baz
{
    private readonly string frob;

    public Baz()
    {    
         // Can be set once in the constructor
         // Only valid on members, not local variables
         frob = "frob";
    }
}

保证一些实例一旦实例化就不会被改变,这将是一件好事。 constreadonly在很小程度上做到这一点,但范围有限。我只能使用const作为编译时常量,readonly作为成员变量。

有没有办法在初始实例化之后给出局部变量不变性(readonly的工作方式,但在更一般的层面上)?


<子> Scala使用var关键字执行此操作,该关键字声明了一个新的不可变值,在获取其初始值后无法重新分配:

var xs = List(1,2,3,4,5) // xs is a value - cannot be reassigned to
xs = List(1,2,3,4,5,6);  // will not compile

2 个答案:

答案 0 :(得分:5)

除了字段之外,您无法阻止在C#中重新分配变量,正如您已经提到的那样使用constreadonly

您可以通过包装它来创建任何现有可变类型的自己的不可变版本,或者如果它是您自己的类,重新编写它是不可变的但是您无法在方法中实现变量,这是您的问题似乎到了。

F#有一些不可变性的选项(如果我没记错的话,是'let关键字)C#没有,所以如果你还想利用.NET的强大功能,可能值得一看F#但具有完全不变性。

答案 1 :(得分:1)

如果包装器是静态的,则无法覆盖。这样就会对变量名称和类型安全性进行编译时编译。

public static class ReadOnly
{
    private static readonly Dictionary<string, object> values = new Dictionary<string, object>();

    public static bool SetValue(string name, object data)
    {
        if (values.ContainsKey(name))
            return false;

        values[name] = data;

        return true;
    }

    public static object GetValue(string name)
    {
        return values[name];
    }
}


        ReadOnly.SetValue("xs", 1);
        ReadOnly.SetValue("xs", 1); // will crash