Подтвердить что ты не робот

Объект С# readonly

Есть ли способ вернуть экземпляр только для чтения объекта?

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

Это единственный способ сделать это, возвращая Clone(), чтобы любые изменения были сделаны с Clone, а не с оригиналом? Я знаю, что для массивов существует функция возврата массива как доступная только для чтения. О, и я знаю, что это ссылочный тип... Я, кроме того, задаюсь вопросом, есть ли какая-то скрытая функция С# для блокировки записи.

Я пытался создать общий класс оболочки ReadOnly, но не мог понять, как получить свойства как readonly, не делая дорогого отражения и такого.

О, и я действительно пытаюсь избежать создания второй версии класса, которая является всеми свойствами readonly. В этот момент я мог бы также вернуть клон.

4b9b3361

Ответ 1

Чтобы спасти себя от создания дополнительного класса, вы можете заставить его реализовать его как интерфейс 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!
}
}

Ответ 2

Вы можете заморозить объект (сделать его неизменным) в некоторых условиях с помощью Castle.DynamicProxy. Подробнее читайте в этом блоге post.

Ответ 3

Вы можете преобразовать класс 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; } 

} 

Ответ 4

Нет такой функции - вы указали свои варианты.

Либо клонировать его, либо использовать тип Person только для чтения. Последний подход обычно предпочтительнее, поскольку семантика понятна: для вызывающих абонентов очевидно, что они не должны (и не могут) модифицировать экземпляр.

Ответ 5

Невозможно сделать все свойства вашего объекта readonly извне из класса. В приведенном выше примере вы не можете использовать свойства _manager только для чтения, если только вы не изменили свойства класса Person для чтения только.

Вы можете сделать сеттер свойств класса Person внутренним, что означает, что только классы внутри той же сборки, что и Person, могут изменять свойства.

Или, если вы сделаете сеттер свойств private, то только код внутри Person может изменить значения свойств.

Ответ 6

Здесь приведен другой пример, основанный на том, как List.AsReadOnly реализован в .NET Framework 2.0. Логическое (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;
        }
    }
}

Чтобы проверить это:

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
}

Ответ 7

Нет. Вы ищете нечто вроде С++ - style const -ness, а для различные причины С# этого не имеет.

Однако анонимные типы действительно неизменяемы.

Ответ 8

Анонимные объекты доступны только для чтения.