不允许更改对象

Ima*_*mad 2 c#

我有一个只读对象,但它的属性在某处得到更新。是否C#有任何限制也可以通过直接更改和反射来限制?

这是POC代码

class Program
{
    static void Main(string[] args)
    {
        ReadOnlyCreator tester = new ReadOnlyCreator();
        tester.ModifyTester();
        Console.ReadLine();
    }
}

class ClassUnderTest
{
    public string SomeProp { get; set; }
}

class ReadOnlyCreator
{
    private readonly ClassUnderTest _classUnderTest;
    public ReadOnlyCreator()
    {
        _classUnderTest = new ClassUnderTest { SomeProp = "Init" };
    }

    public void ModifyTester()
    {
        Console.WriteLine("Before: " + _classUnderTest.SomeProp);
        var modifier = new Modifier(_classUnderTest);
        modifier.Modify();
        Console.WriteLine("After: " + _classUnderTest.SomeProp);
    }
}
class Modifier
{
    private ClassUnderTest _classUnderTest;
    public Modifier(ClassUnderTest classUnderTest)
    {
        _classUnderTest = classUnderTest;
    }

    public void Modify()
    {
        _classUnderTest.SomeProp = "Modified";
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*asH 7

如果你想要一个只读对象,你应该让它只读。IE

class ClassUnderTest
{
    public string SomeProp { get;  }
    public ClassUnderTest(string someProp) => SomeProp = someProp;
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 c#9,您也可以使用init only setter。这允许仅在构造对象期间设置属性:

class ClassUnderTest
{
    public string SomeProp { get; init; }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用值类型,您可以(并且应该)将整个类型声明为只读。另请参阅在类和结构之间进行选择

public readonly struct StructUnderTest
Run Code Online (Sandbox Code Playgroud)

这不能防止反射或不安全的代码。使用这些功能是故意规避规则,因此由开发人员来确保其安全。

  • @Liam `struct` 本身并不意味着它是不可变的;执行此操作的是“readonly struct”中的“readonly”,并且:这就是*OP想要的*;不过,“struct”部分还有“其他”含义 - 围绕相等、装箱、按值复制以及其他一些更相关的内容 (2认同)
  • @Imad 第一个示例在 c# 8 及更早版本中运行良好。您将需要创建一个构造函数,但这通常是一个好主意,以确保所有属性均已实际设置。 (2认同)