猿问

在 C# 中,删除对象的 Action 会发生什么?

我想为我的 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);

}

然而,骑士给了我警告:

看来骑士是在说我的“新”毫无意义。如果我遵循 Rider 的指示,this.RemoveClonedObj = node.RemoveClonedObj;在删除原始 TreeNode 后,使用我复制的 TreeNode 的操作会发生什么?他们也会被移除吗?如果是这样,为什么 Rider 会给我这样的警告?



一只萌萌小番薯
浏览 174回答 2
2回答

摇曳的蔷薇

在 C# 2.0 或更高版本中,以下代码是等效的(DelegateType是委托类型,顾名思义):newDelegate = new DelegateType(oldDelegate);newDelegate = oldDelegate;此类操作将始终创建 的新实例DelegateType,该实例与oldDelegate. 它们并不引用同一个对象(不要被=赋值所混淆):new D(E) 形式的 delegate_creation_expression(其中 D 是 delegate_type,E 是表达式)的绑定时处理由以下步骤组成:如果 E 是方法组,则委托创建表达式的处理方式与从 E 到 D 的方法组转换(Method group conversions)相同。如果 E 是匿名函数,则委托创建表达式的处理方式与从 E 到 D 的匿名函数转换(匿名函数转换)相同。如果 E 是一个值,则 E 必须与 D 兼容(委托声明),并且结果是对新创建的 D 类型委托的引用,该委托引用与 E 相同的调用列表。如果 E 与 D 不兼容,则会发生编译时错误。所以关于你的问题删除原始 TreeNode 后,我复制的 TreeNode 的操作会发生什么?他们也会被移除吗?他们不会有什么事。它们不会被删除。顺便说一句,由于您正在尝试对树节点进行深层复制,因此我怀疑这是否是正确的方法。尽管您创建了委托的新实例,但与其关联的类实例(将调用成员方法的实例)保持不变。

ABOUTYOU

不要将实例方法相互链接。这会导致内存泄漏。即使在原始节点被删除并且代码不再需要之后,由于副本的引用,原始实例将存在于内存中并且不会被垃圾收集。我怀疑这不是你想要的,测试代码class Program{&nbsp; &nbsp; static void Main(string[] args)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; First t = new First();&nbsp; &nbsp; &nbsp; &nbsp; Second s = new Second();&nbsp; &nbsp; &nbsp; &nbsp; t.Print = s.TestMethod;&nbsp; &nbsp; &nbsp; &nbsp; s.test = "change";&nbsp; &nbsp; &nbsp; &nbsp; s = null;&nbsp; &nbsp; &nbsp; &nbsp; t.Print("Hell"); // can debug and see that the function call goes through and string test is = "change"&nbsp; &nbsp; }}public class First{&nbsp; &nbsp; public string s;&nbsp; &nbsp; public Action<string> Print;}public class Second{&nbsp; &nbsp; public string test = "created";&nbsp; &nbsp; public void TestMethod (string test)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var res = "hello" + test + test;&nbsp; &nbsp; }}节点上的方法应该是 Node 对象的一部分,这样您就不必将它们分配给新节点,或者它们应该位于单独的类中,最好是静态的,以便创建新节点不会导致内存问题。
随时随地看视频慕课网APP
我要回答