Можно ли реализовать методы расширения в общих интерфейсных коллекциях в VB.NET? - PullRequest
3 голосов
/ 26 июня 2019

Мне не удается написать метод расширения VB.NET, который можно вызвать из объекта типа ListOfTests в приведенном ниже решении.

Я могу написать метод расширения в 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?

1 Ответ

1 голос
/ 27 июня 2019

Не такая же элегантность и безопасность компиляции, как работает:

<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
...