GRCook Ответов: 2

Переопределение переопределяемого свойства, не распознанного пользователем VB.NET-что?


Я создал базовый класс с Переопределяемыми свойствами:
Public Class MyBaseClass
Inherits Panel

  Public Overridable Property ProcessArguments As String = ""

  Public Overridable Property ProcessFilePath As String = ""

End Class

Затем я добавил производный класс:
Public Class MyDerivedClass
Inherits MyBaseClass

  Public Overrides Property ProcessArguments As String
    Get
      Return My.Settings.MyProcessArguments
    End Get
    Set(value As String)
      My.Settings.MyProcessArguments = value
      My.Settings.Save()
    End Set
  End Property

  Public Overrides Property ProcessFilePath As String
    Get
      Return My.Settings.MyProcessFilePath
    End Get
    Set(value As String)
      My.Settings.MyProcessFilePath = value
      My.Settings.Save()
    End Set
  End Property

End Class

Я ожидал бы, что VB распознает переопределения производного класса, но когда я добавляю производную панель в свою форму, дизайнер инициализирует ее как таковую:
'
'MyDerivedClass1
'
Me.MyDerivedClass1.Location = New System.Drawing.Point(13, 13)
Me.MyDerivedClass1.Name = "MyDerivedClass1"
Me.MyDerivedClass1.ProcessArguments = ""
Me.MyDerivedClass1.ProcessFilePath = ""
Me.MyDerivedClass1.Size = New System.Drawing.Size(184, 255)
Me.MyDerivedClass1.TabIndex = 2

Разве я не перекрываю все должным образом? Я кодирую уже много лет и часто использую переопределенные свойства и методы. Есть идеи?

Я кодирую с использованием VS Community 2019 версии 16.3.9 и .NET Framework версии 4.8.03752, хотя проект ориентирован на платформу версии 4.7.2.

Заранее благодарю вас за любую помощь!

Что я уже пробовал:

Я пробовал помещать определения базового и производного классов в одни и те же или разные проекты, без какой-либо разницы в результате. Я также попытался украсить производные свойства атрибутом DesignerSerializationVisibilityAttribute, установленным в Hidden (конструктор все еще инициализирует его, как показано выше).

Когда я запускаю программу, я получаю пустую строку, даже если значения My.Settings установлены на соответствующие строковые значения.

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

2 Ответов

Рейтинг:
14

OriginalGriff

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

Снять инициализации тестов:

Public Class MyBaseClass
    Inherits Panel

    Public Overridable Property ProcessArguments As String

    Public Overridable Property ProcessFilePath As String

End Class
И он сделает то, что ты хотел. Как бы...

Почему "вроде того"? Потому что это также довольно плохая идея: это означает, что если какой-либо из ваших экземпляров класса установит значение, это повлияет на каждый экземпляр класса, и у вас не будет никакого контроля над тем, кто "выиграет", если вы их используете. Я бы настоятельно рекомендовал вам сделать это через общее свойство, чтобы было более очевидно, что может быть только одно резервное хранилище.


GRCook

Спасибо за вашу помощь. Удаление инициализаторов действительно работало, насколько это касалось кода конструктора. Однако сетка свойств конструктора по-прежнему не показывала значения My.Settings, поэтому я решил пойти другим путем и вместо этого создать пользовательский интерфейс для спецификаций приложений.

Ваша точка зрения о конфликте с несколькими элементами управления также была полезна, хотя это был производный тип с одним экземпляром.

Однако мне интересно, идет ли конфликт инициализаторов базового класса вразрез с концепциями наследования и переопределений? Было бы разумно инициализировать базовый класс, но разве производное определение не должно иметь приоритет в конструкторе?

OriginalGriff

Почему? Производный класс - это базовый класс с добавленной функциональностью, поэтому базовый класс должен быть полностью инициализирован, прежде чем любой код производного класса может быть выполнен (или он не может использовать какие-либо данные или методы базового класса в своем инициализаторе. И система не знает, что вы эффективно пытаетесь переопределить инициализатор базового класса!

Рейтинг:
0

Ralf Meier

Еще одно предложение - дополнительное к тому, что сделал Грифф :
Если ваш базовый класс не использует эти свойства, но вы хотите иметь их в более поздних производных классах - возможно, интерфейс также может быть хорошей идеей. Интерфейс гарантирует, что производные классы действительно обладают этими свойствами ... И... вы получаете также возможность попросить его путем размышления (если это необходимо или интересно).


GRCook

Интерфейсы могут быть полезны, но в этом случае базовый тип был предназначен для общего использования - производный класс должен был просто перенаправить источник для этих свойств и добавить несколько других вещей. Однако Спасибо за Ваш вклад!