简体   繁体   English

c #readonly对象

[英]c# readonly object

Is there any way to return a readonly instance of an object? 有没有办法返回对象的只读实例?

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!
    }
}

Is the only way to do this by returning a Clone() so that any changes are done to the Clone and not the original? 唯一的方法是通过返回克隆()来执行此操作,以便对克隆而不是原始进行任何更改? I know for Arrays there is a function to return the Array as read-only. 我知道对于Arrays,有一个函数可以将Array作为只读方式返回。 Oh, and I know this is a reference type... I'm moreover wondering if there's some hidden C# feature to lock the writing portion. 哦,我知道这是一个参考类型...我还想知道是否有一些隐藏的C#功能来锁定写入部分。

I was trying to come up with a Generic ReadOnly wrapper class, but couldn't figure out how to get the properties as readonly without doing some expensive reflection and the such. 我试图想出一个Generic ReadOnly包装器类,但是如果没有做一些昂贵的反射等等,就无法弄清楚如何将属性作为readonly。

Oh, and I'm really trying to avoid creating a second version of the class that is all readonly properties. 哦,我真的试图避免创建所有只读属性的类的第二个版本。 At that point, I might as well return the clone. 那时,我不妨返回克隆。

To save yourself from creating an extra class, you could make it implement it as an interface IPerson that only has read only properties. 为了避免创建额外的类,您可以将其实现为仅具有只读属性的接口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!
}
}

You can transform the Person class into an immutable object, as below.. 您可以将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; } 

} 

You can freeze object (make it immutable) under some conditions with help of Castle.DynamicProxy . Castle.DynamicProxy帮助下,您可以在某些条件下冻结对象(使其Castle.DynamicProxy不可变)。 Read this blog post for details. 阅读此博客文章了解详情。

There is no such feature - you've covered your options. 没有这样的功能 - 你已经涵盖了你的选择。

Either clone it or make a read-only Person type. 克隆它或制作只读的Person类型。 The latter approach is usually preferred because the semantics are clearer: it's obvious to callers that they shouldn't (and can't) modify the instance. 后一种方法通常是首选的,因为语义更清晰:对于调用者来说,他们不应该(也不能)修改实例是显而易见的。

Here an other example, based on how List.AsReadOnly is implemented in the .NET Framework 2.0. 这是另一个例子,基于如何在.NET Framework 2.0中实现List.AsReadOnly。 A boolean (IsReadOnly) is used in appropriate methods to prevent updates: 在适当的方法中使用布尔值(IsReadOnly)来防止更新:

public class Person
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (!IsReadOnly) _firstName = value;
            else throw new AccessViolationException("Object is read-only.");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            if (!IsReadOnly) _lastName = value;
            else throw new AccessViolationException("Object is read-only.");
        }
    }

    internal virtual bool IsReadOnly { get { return false; } }

    public ReadOnlyPerson AsReadOnly()
    {
        return new ReadOnlyPerson(this);
    }

    public class ReadOnlyPerson : Person
    {
        private Person _person;
        internal override bool IsReadOnly { get { return true; } }

        internal ReadOnlyPerson(Person person) // Contructor
        {
            this._person = person;
        }
    }
}

To test it : 测试它:

static void Main(string[] args)
{
    Person p1 = new Person();
    p1.FirstName = "Joe";
    p1.LastName = "Bloe";
    Console.WriteLine("First = {0} Last = {1}", p.FirstName, p.LastName);

    var p2 = p1.AsReadOnly();
    p2.FirstName = "Josephine"; // AccessViolationException
}

There is not a way to make all the properties of your object readonly externally from the class. 没有办法在类外部只读取对象的所有属性。 In your example above, you cannot make the _manager properties readonly, unless you changed the properties within the Person class to be readonly. 在上面的示例中,除非将Person类中的属性更改为只读,否则不能将_manager属性设置为只读。

You can make the setter of properties of the Person class internal, meaning that only classes within the same assembly as Person can change the properties. 您可以将Person类的属性的setter设置为internal,这意味着只有与Person相同的程序集中的类才能更改属性。

Or, if you make the setter of the properties private, then only code within Person can change the values of the properties. 或者,如果您将属性的setter设为private,则只有Person中的代码才能更改属性的值。

No. You're looking for something like C++-style const -ness, and for various reasons C# doesn't have that. 不。你正在寻找像C ++这样的东西 - 样式const ,并且出于各种 原因, C#没有这个。

However, anonymous types are truly immutable. 但是,匿名类型确实是不可变的。

匿名对象是只读的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM