Договорились, а как насчет обновленной версии?

t можно использовать обобщенные значения, чтобы функция могла принимать аргументы, которые поддерживают один или несколько интерфейсов, и являются производными от базового типа, даже если не существует какого-либо единственного типа, из которого происходят все допустимые типы аргументов. Например, можно сказать:

Sub Foo(Of T As {IInterface1, IInterface2, SomeBaseType})(Param as T)

и разрешено передавать любую производную SomeBaseType, которая реализует как IInterface1, так и IInterface2. Это будет работать, даже если SomeBaseType не поддерживает Interface1 и Interface2, и классы, которые реализуют эти интерфейсы, не имеют общего предка, который также реализует их.

Это может быть очень удобно, если не нужно хранить параметр где-либо после выхода из функции. К сожалению, я не могу найти способ сохранить переданный параметр таким образом, чтобы впоследствии его можно было передать в аналогичную функцию, за исключением, возможно, использования Reflection. Есть ли хороший способ сделать это?

Самое близкое, что я смог придумать, - это определить интерфейс INest (возможно, не лучшее имя - кто-нибудь может его улучшить?), Таким образом:

Interface INest(Of Out T)
    Function Nest() As T
End Interface

А для любого интерфейса, который будет использоваться в сочетании с другими или с «ограничением» базового класса, определите общую версию, как показано ниже

Interface IFun1
    ' Any members of the interface go here, e.g. ...'
    Sub DoFun1()
End Interface

Interface IFun1(Of Out T)
    ' This one does nothing but inherit'
    Inherits IFun1, INest(Of T)
End Interface

Класс, который будет поддерживать несколько интерфейсов, должен объявить себя реализующим универсальные интерфейсы с самим собой в качестве аргумента типа.

Class test123a
    Inherits sampleBase
    Implements IFun1(Of test123a), IFun2(Of test123a), IFun3(Of test123a)
End Class

Если это сделано, можно определить аргумент функции или переменную класса, которая поддерживает несколько ограничений таким образом:

Dim SomeField as IFun1(Of IFun2(Of IFun3(Of sampleBase)))

и затем назначьте ему любой класс, производный от sampleBase, который реализует эти интерфейсы. SomeField будет реализовывать IFun1; SomeField.Nest будет реализовывать IFun2; SomeField.Nest.Nest будет реализовывать IFun3. Обратите внимание, что не требуется, чтобы IFun1, IFun2, IFun3 или sampleBase совместно использовали какие-либо общие производные, кроме универсальных интерфейсов, наследуемых от INest (Of T). Также обратите внимание, что независимо от того, сколько производных от INest интерфейсов реализует класс, ему нужно только определить одну реализацию INest (Of T) .Nest.

Не совсем красиво, но в этом есть две приятные вещи: (1) любой конкретный класс, который фактически реализует необходимые интерфейсы, может быть назначен непосредственно полю, объявленному, как указано выше, без приведения типов; (2) хотя поля, которые связывают типы в другом порядке, не совместимы по присваиванию, они могут быть преобразованы по типу друг в друга.

Есть ли лучший способ хранить что-либо таким образом, чтобы «известно», что оно поддерживает несколько интерфейсов и является производным от определенного базового типа? Учитывая, что можно написать такой код безопасным для типов способом, может показаться, что .net 2.0 CLR, вероятно, вполне может поддерживать такую ​​вещь, если компиляторы предложат небольшую помощь. Я не знаю ни одного особенно приятного подхода с существующими компиляторами.

Ответы на вопрос(1)

Ваш ответ на вопрос