c #readonly对象

m-y*_*m-y 22 c# object readonly reference-type

有没有办法返回对象的只读实例?

public class Person
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
}

public class SomeClass
{
    public SomeClass(Person manager)
    {
        if (manager == null)
            throw new ArgumentNullException("manager");

        _manager = manager;
    }

    private readonly Person _manager;
    public Person Manager
    {
        get { return _manager; } //How do I make it readonly period!
    }
}
Run Code Online (Sandbox Code Playgroud)

唯一的方法是通过返回克隆()来执行此操作,以便对克隆而不是原始进行任何更改?我知道对于Arrays,有一个函数可以将Array作为只读方式返回.哦,我知道这是一个参考类型...我还想知道是否有一些隐藏的C#功能来锁定写入部分.

我试图想出一个Generic ReadOnly包装器类,但是如果没有做一些昂贵的反射等等,就无法弄清楚如何将属性作为readonly.

哦,我真的试图避免创建所有只读属性的类的第二个版本.那时,我不妨返回克隆.

sta*_*son 38

为了避免创建额外的类,您可以将其实现为仅具有只读属性的接口IPerson.

public interface IPerson
{
    string FirstName { get; }
    string LastName { get; }
}
public class Person:IPerson
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
}

public class SomeClass
{
public SomeClass(Person manager)
{
    if (manager == null)
        throw new ArgumentNullException("manager");

    _manager = manager;
}

private readonly Person _manager;
public IPerson Manager
{
    get { return _manager; } //How do I make it readonly period!
}
}
Run Code Online (Sandbox Code Playgroud)

  • 我也喜欢这个,但是将它们重新投入Person类并不容易吗?`Person iCanChangeProperties =(Person)SomeClass.Manager;`并且Cast不会使用该引用来保护它们对属性进行更改...我可能只需坚持克隆.虽然,ReadOnly接口会很好,所以反射告诉他们他们不能**做setter属性. (6认同)
  • @myermian,你说的没错.虽然在用户方面投射它会是一种糟糕的做法.使Person内部可以阻止(但会阻止他们构建新的).即使标记为内部,使用反射,他们也可以访问设置者.另外,传回一个克隆不会阻止用户反映SomeClass并直接获取*_manager*.你不能阻止人们在脚下射击.在有人开始反对你暴露的API时,他们应该得到任何后果. (4认同)

Jer*_*ing 6

您可以将Person类转换为不可变对象,如下所示.

public class Person 
{ 
    public Person( string firstName, string lastName )
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public String FirstName { get; private set; } 
    public String LastName { get; private set; } 

} 
Run Code Online (Sandbox Code Playgroud)