Lev*_*i H 5 vb.net extension-methods
这是我在vb.net中发现的一些我无法弄清楚的东西,我刚刚得到一个带有树视图的表单,然后是以下内容:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
treeTest.Nodes.Add("a")
treeTest.Nodes(0).Test()
End Sub
Run Code Online (Sandbox Code Playgroud)
测试是一种扩展方法:
Imports System.Runtime.CompilerServices
Public Module ExtModule
<Extension()>
Public Sub Test(ByRef node As TreeNode)
End Sub
End Module
Run Code Online (Sandbox Code Playgroud)
如果我使用ByRef,那么我的树视图看起来像:

通过ByVal我得到:

这似乎完全是倒退,如果我只是发送一个参考,为什么节点出现两次,而如果我复制它只出现一次?
好的,我已经解决了一些正在发生的事情.
它与扩展方法本身相关性很小.它更多的是关于VB如何处理ByRef,以及TreeView.Nodes它的外观有些奇怪的行为.
特别是,如果你改变这个,你会得到完全相同的行为:
treeTest.Nodes(0).Test()
Run Code Online (Sandbox Code Playgroud)
至:
ExtModule.Test(treeTest.Nodes(0))
Run Code Online (Sandbox Code Playgroud)
...即使你删除了ExtensionAttribute.
这里有一些C#代码演示了相同的效果,ref根本没有使用参数或扩展方法:
using System.Drawing;
using System.Windows.Forms;
class Test
{
static void Main()
{
TreeView tree = new TreeView { Nodes = { "a" } };
Form form = new Form { Controls = { tree } };
form.Load += delegate {
TreeNode node = tree.Nodes[0];
tree.Nodes[0] = node;
};
Application.Run(form);
}
}
Run Code Online (Sandbox Code Playgroud)
重要的是这些:
TreeNode node = tree.Nodes[0];
tree.Nodes[0] = node;
Run Code Online (Sandbox Code Playgroud)
当您的空扩展方法有一个ByRef参数时,您的代码等同于上面的C#代码 - 因为VB ByRef通过使用临时变量然后分配回原始属性来伪造"真实" 行为.
当您的空扩展方法有ByVal参数时,您的代码只相当于:
TreeNode node = tree.Nodes[0];
// Do nothing
Run Code Online (Sandbox Code Playgroud)
......并且不会创建第二个节点.