如何防止属性设置器修改私有属性数据

qua*_*els 5 c# oop

让我通过提出一个假设的情况来解释我的问题.让我们从课程开始:

public class PaymentDetails
{
    public int Id {get;set;}
    public string Status {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

然后我又上了一堂课:

public class PaymentHelper
{
    private PaymentDetails _paymentDetails;
    public PaymentDetails MyPaymentDetails{ get { return _paymentDetails; } }

    public PaymentHelper()
    {
        _paymentDetails = new PaymentDetails(); 
    }

    public void ModifyPaymentDetails(string someString)
    {
        // code to take the arguments and modify this._paymentDetails
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,所以我有这两个类.PaymentHelper已将该属性MyPaymentDetails设为只读.

所以我不能像这样实例化PaymentHelper和修改MyPaymentDetails:

PaymentHelper ph = new PaymentHelper();
ph.MyPaymentDetails = new PaymentDetails(); // Not allowed!!! 
Run Code Online (Sandbox Code Playgroud)

但我可以ph.MyPaymentDetails像这样修改里面的公共属性:

ph.MyPaymentDetails.Status = "Some status"; // This is allowed
Run Code Online (Sandbox Code Playgroud)

我如何防止这种情况发生?或者没有好办法吗?

Gra*_*mas 7

属性可以将访问修饰符应用于各个访问者,例如:

public string Status { get; private set; }
Run Code Online (Sandbox Code Playgroud)

访问范围取决于您的情况.保持私有,我相信你可以告诉,意味着只有当前类范围内的元素才能使用setter,protected允许继承者使用它等等.

显然,您的类需要从下到上正确设计,以便在层次结构中进一步使用时考虑适当的范围和强大的管理.

  • @quakkels实际上,你可以暴露一个只暴露getter并让setter离开契约的接口.公开地说,套装不是一种选择. (2认同)

Ada*_*rth 5

该级别的语言构造无法提供保护本身就是属性的复杂类型的属性的想法。

一种选择是设计包含类型,使其使用访问修饰符(公共集,保护集,私有集等)使其属性为只读。

我的首选是将其作为对公共消费者的接口公开:

public class PaymentHelper
{
    private PaymentDetails _paymentDetails;
    public IPaymentDetails MyPaymentDetails{ get { return _paymentDetails; } }

    public PaymentHelper()
    {
        _paymentDetails = new PaymentDetails(); 
    }

    public void ModifyPaymentDetails(string someString)
    {
        // code to take the arguments and modify this._paymentDetails
    }
}

interface IPaymentDetails
{
   int Status { get; }
}
Run Code Online (Sandbox Code Playgroud)

PaymentHelper然后,PaymentDetails类内的代码可以直接使用该类,而该类外的代码PaymentDetails除非将其直接强制转换为类,否则将无法使用,如果不释放PaymentDetails类而仅提供接口,则可以停止。

当然,您永远无法真正阻止可能使用反思来设定事情的坚定的人。我倾向于让这些人破坏代码:-)