Моя цель — иметь серию перегрузок, при которых вызывается правильная версия метода в зависимости от типа параметра (известного только во время выполнения). Однако я столкнулся с интересной проблемой в случае, когда метод, который я хочу перегрузить, является конструктором.
Возьмем следующую структуру наследования:
Public MustInherit Class A
Public Property Common As String
End Class
Public Class X
Inherits A
Public Property Unique1 As String
Public Property Unique2 As String
End Class
Public Class Y
Inherits A
Public Property Unique3 As String
Public Property Unique4 As String
End Class
Базовый класс A
наследуется как X
, так и Y
.
Теперь возьмите этот класс, который я буду использовать, чтобы показать проблему:
Public Class Foo
Public Sub New(v As X)
Common = v.Common
Prop1 = v.Unique1
Prop2 = v.Unique2
Prop3 = "Some value"
Prop3 = String.Empty
End Sub
Public Sub New(v As Y)
Common = v.Common
Prop1 = "Some value"
Prop2 = String.Empty
Prop3 = v.Unique3
Prop4 = v.Unique4
End Sub
Public ReadOnly Property Common As String
Public ReadOnly Property Prop1 As String
Public ReadOnly Property Prop2 As String
Public ReadOnly Property Prop3 As String
Public ReadOnly Property Prop4 As String
Public Shared Sub Bar(v As X)
End Sub
Public Shared Sub Bar(v As Y)
End Sub
End Class
Есть обычный метод Bar
с перегрузкой, а также конструктор New
с перегрузкой. Первый New
имеет ту же подпись, что и первый Bar
, а второй New
имеет ту же подпись, что и второй Bar
.
Наконец, возьмите этот тестовый код:
Public Sub Test()
Dim Param As Object = New X
'This works fine
Foo.Bar(Param)
'This gives a compile error
Dim Thing As New Foo(Param)
End Sub
Кажется, у компилятора нет проблем с вызовом Bar
, но для вызова конструктора я получаю следующую ошибку компиляции:
Разрешение перегрузки не удалось, так как ни один доступный «Новый» не может быть вызван без сужающего преобразования:
«Общедоступная подпрограмма «Новый (v As X)»: Параметр соответствия аргумента «v» сужается от «Объекта» до «X».
'Public Sub New (v As Y)': Параметр сопоставления аргументов 'v' сужается с 'Object' до 'Y'.
Почему вызов конструктора вызывает ошибку, а вызов Bar
— нет.
Кроме того, если я изменю объявление Param
на Dim Param As A = New X
, ни один из них не будет компилироваться.
Я чувствую, что должен понять это, но по какой-то причине я этого не понимаю. Может ли кто-нибудь объяснить мне, почему это не работает, и, возможно, предложить обходной путь?
Option Strict Off
, поставьOn
и будет понятнее.Dim Param As New X()
будет работать для обоих. - person Jimi   schedule 02.04.2021Dim Param As New X
сработает, но в этом нет смысла. Моя цель состоит в том, чтобы иметь серию перегрузок, при которых правильная версия метода вызывается в зависимости от типа параметра (известного только во время выполнения). - person Keith Stein   schedule 02.04.2021Option Strict
в том, что вы увидите, что обе конструкции терпят неудачу во время компиляции, поэтому вам не нужно спрашивать себя, почему одна из них терпит неудачу?, потому что на самом деле обе конструкции терпят неудачу, это просто временно скрыто от вас. - person Jimi   schedule 02.04.2021Bar
работают как положено.Dim Param As Object = New X
приводит к вызовуBar(v As X)
, аDim Param As Object = New Y
приводит к вызовуBar(v As Y)
. Только перегрузки конструктора вызывают какую-либо ошибку. - person Keith Stein   schedule 02.04.2021X
иY
(в реальном коде) имеют разные члены, которые уникальны, и разные перегрузки методов должны обрабатывать два типа по-разному. - person Keith Stein   schedule 02.04.2021Option Strict Off
. Установив егоOn
, как построениеFoo
, так и вызовBar()
не разрешены, потому что не разрешено неявное преобразование (как и должно быть). Это похоже на разрешение неявного преобразования между типами, скрытие сужающих или расширяющих преобразований. Таким образом, вы суммируете целые числа со строками с автоматическим обнадеживающим преобразованием между тем или иным типом. Удачи. -- Реализация интерфейса не имеет ничего общего с конкретными реализациями или наличием специализированных методов/свойств в классах, реализующих интерфейс. - person Jimi   schedule 02.04.2021Option Strict
вариант. Я понимаю, что есть преимущества, но я хотел бы избежать обсуждения плюсов и минусов в этих комментариях. В приведенном выше кодеOption Strict
равноOff
; разрешено неявное преобразование. Тем не менее, кажется, я не понимаю, как вы хотите, чтобы я реализовал и использовал интерфейс. Если вы хотите опубликовать ответ с некоторым кодом, показывающим мне пример этого, я был бы рад его увидеть. - person Keith Stein   schedule 02.04.2021Z
, который наследуетA
, а соответствующего конструктора или общего метода нет?) Я искал и не смог найти простого ответа на вопрос, почемуOption Strict Off
кажется игнорируемым для конструкторов. - person Sean Skelly   schedule 03.04.2021A
, во время выполнения и убедиться, что над ним запускается правильная функция), вам необходимо предоставить нам дополнительную информацию о том, как может выглядеть эта функция. как. Добавьте больше мяса к костям вашего примера кода, и тогда мы, вероятно, сможем показать вам, как выглядит интерфейсное решение. - person Sean Skelly   schedule 03.04.2021Z
я бы ожидал исключения. Что касается вашего запроса на дополнительную информацию, я добавил в свой пример кода. Дайте мне знать, если вам нужна дополнительная информация, и я постараюсь соответствующим образом обновить свой вопрос. - person Keith Stein   schedule 03.04.2021Option Strict Off
заключается не только в том, что этоOff
(со всеми вытекающими отсюда последствиями), но и в том, что вы затем структурируете свое приложение, имея в виду своего рода слабо типизированную модель, поэтому слишком много частей кода полагаются на эту не- функция (сделанная для облегчения миграции VB6), пытаясь игнорировать строго типизированную платформу, с которой вы работаете. Это генерирует код, который просто скрывает проблемы. -- Вы пытаетесь построить общую структуру, но не хотите говорить об интерфейсах. .Net использует для этого интерфейсы, а не типObject
, и наследование ограничено одним классом. - person Jimi   schedule 03.04.2021