如何让会员深度只读



我有一个类,它有一个只读成员

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类。

最新更新