В C #, что будет с действием удаленного объекта? - PullRequest
0 голосов
/ 30 сентября 2019

Я хочу сделать глубокую копию для моего класса TreeNode. Вот мой код:

    public TreeNode(TreeNode node, GUIStyle inPointStyle, GUIStyle outPointStyle, Action<ConnectionPoint> OnClickInPoint, Action<ConnectionPoint> OnClickOutPoint)
{
    this.rect = new Rect(node.rect);
    this.style = new GUIStyle(node.style);
    this.inPoint = new ConnectionPoint(this, ConnectionPointType.In, inPointStyle, OnClickInPoint);
    this.outPoint = new ConnectionPoint(this, ConnectionPointType.Out, outPointStyle, OnClickOutPoint);
    this.defaultNodeStyle = new GUIStyle(node.defaultNodeStyle);
    this.selectedNodeStyle = new GUIStyle(node.selectedNodeStyle);
    this.allDecorations = new List<GameObject>(node.allDecorations);
    this.objs = new Dictionary<GameObject, IndividualSettings>(node.objs);
    this.name = String.Copy(node.name);
    this.RemoveClonedObj = new Action(node.RemoveClonedObj);
    this.OnChangeView = new Action<TreeNode>(node.OnChangeView);
    this.OnRemoveNode =  new Action<TreeNode>(node.OnRemoveNode);
    this.OnCopyNode = new Action<TreeNode>(node.OnCopyNode);
    this.PreviewTree = new Action<TreeNode, bool> (node.PreviewTree);
}

Однако Всадник предупредил меня:

enter image description here

Кажется, всадник говорилчто мое "новое" не имеет смысла. Если я буду следовать инструкции Rider, используйте this.RemoveClonedObj = node.RemoveClonedObj; что произойдет с действиями моего скопированного TreeNode после удаления оригинального TreeNode? Будут ли они также удалены? Если так, почему Райдер дает мне такое предупреждение?

Ответы [ 2 ]

2 голосов
/ 30 сентября 2019

В C # 2.0 или выше следующие коды эквивалентны (DelegateType - тип делегата, как следует из его названия):

newDelegate = new DelegateType(oldDelegate);
newDelegate = oldDelegate;

(см. MSDN - Как: Объявить, создать и использовать делегата (Руководство по программированию в C #) )

Кроме того, Microsoft указывает (см. здесь ), что такая операция всегда будет создавать новый экземпляр DelegateType, который имеет тот же список вызовов, что и oldDelegate. Они не ссылаются на один и тот же объект (не путайте с присваиванием =):

Обработка времени привязки выражения Delegate_creation_exp вида new D (E), где Dявляется типом делегата, а E является выражением, состоит из следующих шагов:

  • Если E является группой методов, выражение создания делегата обрабатывается так же, как преобразование группы методов (Преобразование группы методов) из E в D.

  • Если E является анонимной функцией, выражение создания делегата обрабатывается так же, как преобразование анонимной функции (преобразования анонимной функции) из Eв D.

  • Если E - это значение, E должно быть совместимо (объявления делегатов) с D, , а результатом является ссылка на вновь созданный делегат типа D, которыйссылается на тот же список вызовов, что и E . Если E не совместим с D, возникает ошибка компиляции.

Так что по вашему вопросу

Что произойдет с моим скопированным TreeNode'sДействия после удаления оригинального TreeNode? Будут ли они также удалены?

С ними ничего не случится. Они не будут удалены.


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

0 голосов
/ 30 сентября 2019

Не связывайте методы экземпляра друг с другом. Это приведет к утечкам памяти.

Даже после того, как исходный узел будет удален и больше не нужен вашему коду, из-за ссылки из копии исходный экземпляр будет жить в памяти и не будет собираться мусором.

Я подозреваю, что это не то, что вам нужно. Тестовый код для этого

class Program
{
    static void Main(string[] args)
    {
        First t = new First();
        Second s = new Second();
        t.Print = s.TestMethod;
        s.test = "change";
        s = null;
        t.Print("Hell"); // can debug and see that the function call goes through and string test is = "change"
    }
}

public class First
{
    public string s;
    public Action<string> Print;
}
public class Second
{
    public string test = "created";
    public void TestMethod (string test)
    {
        var res = "hello" + test + test;
    }
}

Либо ваши методы на узле должны быть частью объекта Node, поэтому вам не нужно их назначатьк новым узлам, или они должны быть в отдельном классе, предпочтительно статическом, чтобы создание новых узлов не приводило к проблеме с памятью.

...