Как мне обойти C # отсутствие перегрузки оператора присваивания - PullRequest
0 голосов
/ 25 октября 2011

Я знаю, что перегрузка оператора присваивания невозможна в C # ... но возможно ли заблокировать оператор по умолчанию?

Ситуация: я разрабатываю сложный структурный редактор. Это позволит комбинировать множество объектов классов и связывать их вместе.

Чтобы сохранить эти ссылки и ссылки между экземплярами многих классов, мне нужно, чтобы у каждого экземпляра был уникальный идентификатор для всех классов. Я создал класс ID (включая ссылку на объект контейнера), чтобы справиться с этим. Чтобы убедиться, что идентификаторы уникальны, я сделал так, чтобы класс регистрировал все свои экземпляры в статическом list<idClass> IDRegister и все ссылки на любой экземпляр идентификатора в статическом list<idClass> IDReferenceList.

Проблема: при первичном назначении / создании нового экземпляра идентификатора для использования я регистрирую идентификатор в IDRegister, эффективно создавая две ссылки на объект. Во время использования любого экземпляра класса теперь слишком легко перезаписать поле идентификатора другим (уже существующим или новым). Обычная перезапись в незарегистрированных объектах оставила бы экземпляр без ссылки, а сборка мусора позаботилась бы об очистке памяти. В этом случае ссылка на экземпляр в IDRegister (и, возможно, несколько раз в IDReferenceList) сохранит ID-экземпляр живым, а вместе с ним ссылки на возможно устаревшие объекты-контейнеры, предотвращающие их очистку. Все это оставит меня с огромной утечкой памяти в моей библиотеке.

Решение

Я не могу принять возможные утечки памяти в моей библиотеке. У меня есть два варианта: перейти на C ++ или найти способ предотвратить переопределение по умолчанию существующей ссылки на экземпляр ID.

или есть третий вариант?

Ответы [ 2 ]

3 голосов
/ 25 октября 2011

Вы можете сделать ваше поле доступным только для чтения (за исключением первоначального назначения, когда объект создается).

Есть два слегка разных способа сделать это. Первый и самый надежный способ - использовать поле readonly с открытым геттером и без сеттера. Тогда id можно установить только в конструкторе.

private readonly int id;

public int Id
{
    get
    {
        return id;
    }
}

Второе - использовать свойство, в котором сеттер сделан приватным:

public int Id { get; private set; }

Это позволяет изменять id после создания, так что это не совсем то же самое, что readonly. Но так как установщик является закрытым, он по-прежнему не позволяет клиентам вашего кода случайно изменить значение.

0 голосов
/ 25 октября 2011

Прежде всего, вы можете сделать поле идентификатора доступным только для чтения, которое устанавливается только при первоначальном назначении.

Во-вторых, если ваше приложение может иметь утечки памяти, значит, вы не выполняете очистку должным образом. Если вы не размещаете данные в куче GC, то вам нужен деструктор (и вообще dispose ()), который обеспечит очистку. Это должно быть сделано где-то, что невозможно обойти. То есть если вас беспокоит утечка памяти, вызванная перезаписью поля идентификатора, значит, ваш деструктор находится в неправильном классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...