将扩展方法 "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
.
接受它来处理对对象实例的直接引用
我想将 "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
.