const修饰符可以(而且通常也应该)用在任何满足以下条件的字段上:它的值在编译时已知,并且在程序的生命周期内不会改变。
private const int num = 1729;
public const string title = "Grand" + " Master";
readonly修饰符可以(而且通常也应该)用在这样的字段上:它无法声明为const,其值在程序的生命周期内不会改变,并且要么由内联初始化器赋值,要么在实例化时赋值(由构造函数或构造函数调用的方法来完成)。
private readonly int num;
private readonly System.Random rand = new System.Random();
public MyClass(int num)
{
this.num = num;
}
在对安全敏感的场景中(或者哪怕只是在一个大型代码库里,开发者们的优先级和目的各不相同),你都应该避免让类的公共 API 被绕过,比如接受并存储方法的可变形参,或者通过返回值、out参数把类的可变成员暴露出去。
readonly修饰符可以防止字段中的值或引用被覆盖,但它无法保护引用类型的成员。
readonly List<int> ints = new List<int>();
void Foo()
{
ints.Add(1); // ok
ints = new List<int>(); // fails to compile
}
要确保引用类型的所有成员都受到保护,可以把字段声明为readonly,并定义不带set访问器的自动属性。
基类库(BCL)在需要阻止集合成员被更新时,提供了一些只读版本的集合。它们以包装器的形式提供:
ReadOnlyDictionary<T>以只读方式公开Dictionary<T>。ReadOnlyCollection<T>以只读方式公开List<T>。你上次在 developer-privileges 中见到的那个身份验证系统现在需要打理一下了。你的任务是清理这些代码。这样一次清理不仅能让以后的维护者省心,还能发现并修复一些安全漏洞。
这是一项重构任务。给Authenticator或Identity中你认为合适的成员加上const修饰符。
这是一项重构任务。给Authenticator类或Identity结构体中你认为合适的字段加上readonly修饰符。
对于Authenticator类或Identity结构体上任何合适的属性,移除set访问器,或将其设为private。
目前,管理员身份字段是通过调用Admin返回的。这样做并不理想,因为调用方可以修改该字段。想办法阻止调用方修改Authenticator对象上的管理员详细信息。
目前,包含硬编码特权开发者身份的字典是通过调用GetDevelopers()返回的。这样做并不理想,因为调用方可以修改该字典。想办法阻止调用方修改Authenticator对象上的开发者详细信息。