Подтвердить что ты не робот

Класс VB.NET наследует базовый класс и реализует проблему с интерфейсом (работает на С#)

Я пытаюсь создать класс в VB.NET, который наследует базовый абстрактный класс, а также реализует интерфейс. Интерфейс объявляет свойство string, называемое Описание. Базовый класс содержит свойство string, называемое Описание. Основной класс наследует базовый класс и реализует интерфейс. Существование свойства Description в базовом классе соответствует требованиям интерфейса. Это отлично работает на С#, но вызывает проблемы в VB.NET.

Во-первых, вот пример кода С#, который работает:

public interface IFoo
{
    string Description { get; set; }
}

public abstract class FooBase
{
    public string Description { get; set; }
}

public class MyFoo : FooBase, IFoo
{
}

Теперь вот версия VB.NET, которая дает ошибку компилятора:

Public Interface IFoo
    Property Description() As String
End Interface

Public MustInherit Class FooBase
    Private _Description As String
    Public Property Description() As String
        Get
            Return _Description
        End Get
        Set(ByVal value As String)
            _Description = value
        End Set
    End Property
End Class

Public Class MyFoo
    Inherits FooBase
    Implements IFoo
End Class

Если я создаю базовый класс (FooBase), реализую интерфейс и добавляю Implements IFoo.Description к свойству, все это хорошо, но я не хочу, чтобы базовый класс реализовал интерфейс.

Ошибка компилятора:

Класс 'MyFoo' должен реализовать 'Property Description() As String' для интерфейса 'IFoo'. У реализации свойства должны быть соответствующие спецификации ReadOnly или WriteOnly.

Может ли VB.NET не обрабатывать это, или мне нужно изменить синтаксис где-нибудь, чтобы заставить это работать?

4b9b3361

Ответ 1

Вам нужно пометить ваше свойство как Overridable или MustOverride в базовом классе, а затем вы можете переопределить его в дочернем классе:

Public MustInherit Class FooBase
    Private _Description As String
    Public Overridable Property Description() As String
        Get
            Return _Description
        End Get
        Set(ByVal value As String)
            _Description = value
        End Set
    End Property
End Class

Public Class MyFoo
    Inherits FooBase
    Implements IFoo
    Public Overrides Property Description() As String Implements IFoo.Description
        Get
            Return MyBase.Description
        End Get
        Set(ByVal value As String)
            MyBase.Description = value
        End Set
    End Property
End Class

Edit Это в ответ на то, что @M.A. Ханин отправил. Оба наших решения работают, но важно понимать последствия каждого из них. Представьте следующий код:

Dim X As FooBase = New MyFoo()
Trace.WriteLine(X.Description)

Что из X.Description? Используя Overridable, вы получите вызов дочернего класса, используя метод Overload, и получите вызов базового класса. Ни то, ни другое неправильно, просто важно понять последствия декларации. Используя метод перегрузки, вы должны выполнить кастинг, чтобы получить реализацию ребенка:

Trace.WriteLine(DirectCast(X, MyFoo).Description)

Если вы просто вызываете MyBase.Description из дочернего класса, вопрос спорный, но если вы когда-либо измените определение дочернего класса, вам просто нужно убедиться, что вы понимаете, что происходит.

Ответ 2

Так или иначе, вы должны указать детали реализации интерфейса IFoo.

Как насчет этой простой опции?

Public Class MyFoo
    Inherits FooBase
    Implements IFoo
    Overloads Property Description() As String Implements IFoo.Description
        Get
            Return MyBase.Description
        End Get
        Set(ByVal value As String)
            MyBase.Description = value
        End Set
    End Property
End Class

Ответ 3

VB требует, чтобы свойство реализации объявляло реализацию. Это из-за того, что я действительно считаю приятной особенностью VB, которую я иногда пропускаю на С#, - что вы можете переименовать элемент, который реализует член интерфейса.

Таким образом, единственный способ сделать эту работу без реализации IFoo.Description в FooBase - объявить Description Overridable, а затем определить MyFoo как:

Public Class MyFoo
    Inherits FooBase
    Implements IFoo

    Public Overrides Property Description() As String Implements IFoo.Description
        Get
            Return MyBase.Description
        End Get
        Set(ByVal value As String)
            MyBase.Description = value
        End Set
    End Property
End Class

Ответ 4

Извините, если я опаздываю на вечеринку и тоже извиняюсь, если эта функция была введена только в .NET 4, но возможно следующее (сейчас)

Public Interface IFoo
    Property Description() As String
End Interface

Public MustInherit Class FooBase
    Implements IFoo

    Public MustOverride Property Description As String Implements IFoo.Description
End Class

Public Class MyFoo
    Inherits FooBase

    Private _description As String

    Public Overrides Property Description As String
        Get
            Return _description
        End Get
        Set(value As String)
            _description = value
        End Set
    End Property
End Class

Ответ 5

VB.NET не поддерживает неявное выполнение. Я также столкнулся с этой проблемой и имел массу проблем.

Когда вы работаете с сгенерированными классами (сущностями и т.д.), где вы должны явно объявлять Implements IFoo, это делает невозможным вообще.

Поэтому Я отправил соединение с Microsoft, и я надеюсь, вы проголосуете и в следующей версии VB они улучшат компилятор, чтобы быть более умными.

Ответ 6

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

Public Class MyFoo
    Inherits FooBase
    Implements IFoo
    Private Property IFoo_Description() As String Implements IFoo.Description
        Get
            Return Me.Description
        End Get
        Set(ByVal value As String)
            Me.Description = value
        End Set
    End Property
End Class

Ответ 7

Это странная проблема, и она явно показывает разницу между компиляторами С# и VB.NET. Я бы предположил, что вы реализуете интерфейс в абстрактном базовом классе, так как это сделает компилятор VB.NET счастливым, и во время выполнения ваш дочерний класс будет по-прежнему иметь метаданные, указывающие, что он действительно реализует IFoo.

Есть ли конкретная причина, согласно которой дочерний класс должен объявить, что он реализует интерфейс?