我有一个类,它有一个只读成员
class A
{
public static readonly Student student = new Student("StudentName");
}
而会员学生不是只读的,我可以
A.student.Name = "Another Name";
学生是我无法更改的第三方类。如何使其深度只读?
您没有。没有什么神奇的关键字不仅可以使引用不可变,还可以使引用所引用的对象不可变。如果您想使其真正不可变,则需要使用不可变对象作为该字段的类型。你可以创建一个包装类来组成你的可变类型,而不公开任何突变运算符,或者创建一个与你现有的类型相当但不可变的新类型,但如果你从这个类中公开现有类型,你就无法阻止某人对其进行突变
您的Student
类应该具有其属性setter private
。如果您无法控制该类,请创建一个包装器,该包装器只有private
setter。
public class Student
{
public string Name { get; private set; }
public Student(string name)
{
Name = name;
}
}
或者包装:
public class StudentWrapper
{
Student _student;
public string Name { get { return _student.Name; } }
public Student(Student student)
{
_student = student;
}
}
您可以对Student类进行子类化,并从那里提供您自己的只读实现,确保每个可公开访问的setter都是最终的。当然,它仍然可以再次返回给学生,但出于您自己的开发目的,您可以确保它在本地"只读"。
或者,您可以将学生类封装在自己的类中,只允许访问getter。
这里有一些示例代码来说明我所描述的方法,因为有些人似乎不相信这是可能的。。。
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Student student = new Student();
student.Name = "Joe";
StudentSubClass studentSubClassed = new StudentSubClass();
studentSubClassed.Name = ""; // THIS LINE IS DISALLOWED FOR COMPILATION.
StudentWrapper studentWrapped = new StudentWrapper(student);
studentWrapped.Name = ""; // THIS LINE IS DISALLOWED FOR COMPILATION.
}
}
class Student
{
public string Name { get; set; }
}
class StudentSubClass : Student
{
public new string Name { get; private set; }
}
class StudentWrapper
{
private Student student;
public StudentWrapper(Student student)
{
this.student = student;
}
public string Name
{
get
{
return this.student.Name;
}
}
}
}
现在,您当然可以将子类化实例强制转换回Student,比如…
var newStudent = (Student)studentSubClassed;
newStudent.Name = "";
这将允许再次访问,但考虑到是你在开发它,那么你可以确保它至少是"合理的"只读的,前提是有人不会回来铸造它,这将破坏你希望通过这种开发实现的目标。
没有任何铁的方法可以确保子类化技术在未来被滥用,尽管这是一种非常合理的方法,前提是要理解为什么要这样做,但有了包装器技术,你就可以确保你的实现不会受到滥用的影响。但是,如果包装后的类将来发生更改,那么您将不得不相应地修改包装器。
另一种选择是简单地将Student类的实现编写为Immutable类。