5

我目前知道在 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
4

2 回答 2

5

您无法阻止在 C# 中重新分配变量,但字段除外,正如您已经提到的使用constor readonly

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

F# 有一些letC# 没有的不变性选项(如果我没记错的话是 ' 关键字),因此如果您仍想利用 .NET 的强大功能但具有完全不变性,则可能值得研究 F#。

于 2013-07-26T14:17:35.737 回答
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
于 2013-07-26T15:10:36.143 回答