在下面的解决方案中,我无法编写一个可以从ListOfTests
类型的对象调用的VB.NET扩展方法。
我可以使用通用类型约束在C#中编写扩展方法。
这是我编写的一些测试代码,用来演示在更大的现有VB.NET解决方案中遇到的问题。
这里讨论的扩展方法是FilterByIDs
,这只是我选择的简短示例。
有效的C#解决方案:
using System;
using System.Collections.Generic;
using System.Linq;
static class TestApp
{
public static void Main()
{
var objTest = new ListOfTests
{
new Test {Id = 1}, new Test {Id = 2}, new Test {Id = 3}
};
objTest.FilterByIDs(new [] {3});
// Prints "3" only - Extension method works
objTest.ForEach(x => Console.WriteLine(x.Id));
}
}
public static class Extensions
{
public static void FilterByIDs<T, TID>(this List<T> target, IEnumerable<TID> objIDs) where T : ITest<TID>
{
target.RemoveAll(x => !objIDs.Contains(x.Id));
}
}
public class ListOfTests : List<Test>
{}
public class Test : ITest<int>
{
public int Id { get; set; }
}
public interface ITest<TID>
{
TID Id { get; }
}
我尝试在VB.NET中编写此代码(无法构建):
Imports System.Runtime.CompilerServices
Class TestApp
Public Shared Sub Main()
Dim objTest As New ListOfTests()
objTest.Add(New Test() With { .ID = 1})
objTest.Add(New Test() With { .ID = 2})
objTest.Add(New Test() With { .ID = 3})
objTest.FilterByIDs({3})
objTest.ForEach(Sub(x) Console.WriteLine(x.ID))
End Sub
End Class
Public Module Extensions
<Extension>
Public Sub FilterByIDs(Of T As ITest(Of TID), TID)(target As List(Of T), objIDs As IEnumerable(Of TID))
target.RemoveAll(Function(x) Not objIDs.Contains(x.Id))
End Sub
End Module
Public Class ListOfTests
Inherits List(Of Test)
End Class
Public Class Test
Implements ITest(Of Integer)
Public Property ID As Integer Implements ITest(Of Integer).ID
End Class
Public Interface ITest (Of T)
Property ID As T
End Interface
VB.NET解决方案的生成错误是
“ TestApp.vb(18,16):[BC36561]扩展方法'FilterByIDs'具有永远无法满足的类型约束。”
是否可以在VB.NET中编写此代码?
答案 0 :(得分:1)
优雅和编译安全性不同,但可以正常工作:
<Extension>
Public Module Extensions
<Extension>
Public Sub FilterByIDs(Of T)(target As IList, objIDs As IEnumerable(Of T))
If (target Is Nothing) Then Throw New NullReferenceException() 'To simulate instance method behavior
For i As Int32 = target.Count - 1 To 0 Step -1
Dim myTest As ITest(Of T) = TryCast(target(i), ITest(Of T))
If (myTest Is Nothing) Then
target.RemoveAt(i)
Else
If (Not objIDs.Contains(myTest.ID)) Then target.RemoveAt(i)
End If
Next
End Sub
End Module