TIANLUN ZHU
TIANLUN ZHU

Reputation: 351

In C#, what will happen for an removed object's Action?

I want to make a deep Copy for my Class TreeNode. Here is my code:

    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);
}

However, the Rider gave me the warning:

enter image description here

It seems the Rider was saying that my "new" is meaningless. If I follow Rider's instruction, usethis.RemoveClonedObj = node.RemoveClonedObj; what will happen for my copyed TreeNode's Actions aftering removing the orginal TreeNode? Will they be removed as well? If so, why does Rider give me such warning?

Upvotes: 0

Views: 147

Answers (2)

ph3rin
ph3rin

Reputation: 4896

In C# 2.0 or above, the following codes are equivalent (DelegateType is a delegate type, as its name suggests):

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

(See MSDN - How to: Declare, Instantiate, and Use a Delegate (C# Programming Guide))

Also, Microsoft specifies (see here) that such operation will always create a new instance of DelegateType, which has the same invocation list as the oldDelegate. They do not refer to the same object (don't be confused by the = assignment):

The binding-time processing of a delegate_creation_expression of the form new D(E), where D is a delegate_type and E is an expression, consists of the following steps:

  • If E is a method group, the delegate creation expression is processed in the same way as a method group conversion (Method group conversions) from E to D.

  • If E is an anonymous function, the delegate creation expression is processed in the same way as an anonymous function conversion (Anonymous function conversions) from E to D.

  • If E is a value, E must be compatible (Delegate declarations) with D, and the result is a reference to a newly created delegate of type D that refers to the same invocation list as E. If E is not compatible with D, a compile-time error occurs.

So regarding your question

What will happen for my copyed TreeNode's Actions aftering removing the orginal TreeNode? Will they be removed as well?

Nothing will happen to them. They will not be removed.


By the way, since you are trying to make a deep copy of your tree-node, I suspect whether it is the correct way. Though you have created a new instance of your delegate, the class instance associated with it (the instance on which member methods will be invoked) stays the same.

Upvotes: 2

peeyush singh
peeyush singh

Reputation: 1407

Do not link instance methods to each other. This will lead to memory leaks.

Even after the original node is removed and no longer needed by your code, due to the reference from the copy the original instance will live in the memory and not be garbage collected.

I suspect this is not what you want, Test code for this

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

Either your methods on the node should be part of the Node object, this way you do not have to assign them to new nodes, or they should be in a separate class, preferably static, so that creation of new nodes does not lead to a memory issue.

Upvotes: 0

Related Questions