将扩展方法 "Move" 添加到泛型 List(Of T)”:T 未定义

Adding an extension method "Move" to generic List(Of T)": T is not defined

我想将 "Move" 方法作为扩展方法添加到 "List(Of...)"。

我想将其添加到通用列表,而不是特定列表。

我的做法是这样的:

Imports System.Runtime.CompilerServices

Module ExtensionMethods
    <Extension()>
    Public Sub Move(ByRef uBase As List(Of T), ByVal index As Integer, ByVal newIndex As Integer)

        Dim item As T = uBase.Item(index)
        uBase.RemoveAt(index)
        uBase.Insert(newIndex, item)

    End Sub

End Module

编译器不接受 "uBase As List(Of T)" 行和“ Dim item As T ="

中的 "T"

这里应该用什么?

非常感谢!

首先,不要在目标参数上使用 ByRef。我稍后会对此进行扩展,因为我想跳到修复编译错误的内容。

其次,为了在List(Of T)中有一个类型参数T,它必须存在于方法定义中,所以你需要在方法上使用(Of T)

Imports System.Runtime.CompilerServices

Module ExtensionMethods
    <Extension()>
    Public Sub Move(Of T)(ByVal uBase As List(Of T), ByVal index As Integer, ByVal newIndex As Integer)
        '          ^^^^^^

        Dim item As T = uBase.Item(index)
        uBase.RemoveAt(index)
        uBase.Insert(newIndex, item)

    End Sub
End Module

规则:扩展方法不应该**接受目标实例使用ByRef

**规则的例外情况:某些值(Structure)类型可能需要通过引用传递给实现引用 type-like 行为(尽管值类型应该尽可能不可变)或实现更好的性能(在 C# 中,您使用 in 关键字以便编译器防止实例发生变化)。

以此扩展方式为例:

Module ExtensionMethods
    <Extension()>
    Public Sub ConfuseMe(Of T)(ByRef list as List(Of T))
        list = New List(Of T)
    End Sub
End Module
Dim myList As List(Of Integer)
Dim myList2 = myList            ' A copy of the reference, but only one list object involved.

myList.Add(0)
myList.Add(1)
myList.Add(2)

myList.ConfuseMe()              ' Call an extension method that can MODIFY myList

myList 不再指向同一个实例。 myList2 指向原始实例,而 myList 指向在 ConfuseMe 中创建的新实例。来电者没有理由期望发生这种情况。

那你为什么要这样做呢?你可能不会。但基于一些评论和引用与引用之间的混淆,我可以看到它是偶然发生的。使用 ByVal 可以防止它成为 difficult-to-track-down 错误。

虽然可以在扩展方法中实现,但不能通过常规实例方法实现。

Class TestClass

    Sub ConfuseMe()
        Me = New TestClass()  ' Not possible on a Class
    End Sub

EndClass
Dim x As New TestClass()
x.ConfuseMe()              ' You wouldn't expect 'x' to refer to a different instance upon return

你不能那样做。它不允许您分配给 Me(同样,值类型是例外),并且您不会期望 x 在这样的调用后指向一个新实例。

出于同样的原因,在扩展方法中执行此操作没有意义,其目的是表现得像实例方法。由于您 不需要 更改调用者的变量,因此无需引用它。只需通过 ByVal.

接受它来处理对对象实例的直接引用