简体   繁体   English

VB.NET 类继承一个基类并实现一个接口问题(在 C# 中工作)

[英]VB.NET class inherits a base class and implements an interface issue (works in C#)

I am trying to create a class in VB.NET which inherits a base abstract class and also implements an interface.我正在尝试在 VB.NET 中创建一个类,它继承了一个基本抽象类并实现了一个接口。 The interface declares a string property called Description.该接口声明了一个名为 Description 的字符串属性。 The base class contains a string property called Description.基类包含一个名为 Description 的字符串属性。 The main class inherits the base class and implements the interface.主类继承基类并实现接口。 The existence of the Description property in the base class fulfills the interface requirements.基类中描述属性的存在满足了接口要求。 This works fine in C# but causes issues in VB.NET.这在 C# 中工作正常,但在 VB.NET 中会导致问题。

First, here is an example of the C# code which works:首先,这是一个有效的 C# 代码示例:

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

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

public class MyFoo : FooBase, IFoo
{
}

Now here is the VB.NET version which gives a compiler error:现在这里是 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

If I make the base class ( FooBase ) implement the interface and add the Implements IFoo.Description to the property all is good, but I do not want the base class to implement the interface.如果我让基类 ( FooBase ) 实现接口并将Implements IFoo.Description添加到属性,一切都很好,但我不希望基类实现接口。

The compiler error is:编译器错误是:

Class 'MyFoo' must implement 'Property Description() As String' for interface 'IFoo'.类“MyFoo”必须为接口“IFoo”实现“Property Description() As String”。 Implementing property must have matching 'ReadOnly' or 'WriteOnly' specifiers.实现属性必须具有匹配的“ReadOnly”或“WriteOnly”说明符。

Can VB.NET not handle this, or do I need to change my syntax somewhere to get this to work? VB.NET 不能处理这个问题,还是我需要在某处更改我的语法才能使其正常工作?

You need to mark your property as Overridable or MustOverride in the base class and then you can override it in the child class:您需要在基类MustOverride您的属性标记为OverridableMustOverride ,然后您可以在子类中覆盖它:

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 This is in response to what @MA Hanin posted.编辑这是对@MA Hanin 发布的内容的回应。 Both of our solutions work but its important to understand the ramifications of each.我们的两种解决方案都有效,但了解每种解决方案的后果很重要。 Imagine the following code:想象一下以下代码:

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

What comes out of the X.Description?从 X.Description 中得出什么? Using the Overridable you'll get the call to the child class while using the Overload method you'll get the call to the base class.使用 Overridable 可以调用子类,而使用 Overload 方法可以调用基类。 Neither is right or wrong, its just important to understand the consequences of the declaration.没有对错,重要的是了解声明的后果。 Using the Overload method you have to up-cast to get the child's implementation:使用 Overload 方法,您必须向上转换才能获得孩子的实现:

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

If you're just calling MyBase.Description from the child class the question is moot but if you ever change the definition of the child class then you just need to make sure you understand what's going on.如果您只是从子类调用 MyBase.Description ,则问题没有意义,但是如果您更改了子类的定义,那么您只需要确保了解正在发生的事情。

One way or the other, you must specify the implementation details of the IFoo interface.一种或另一种方式,您必须指定 IFoo 接口的实现细节。

What about this simple option?这个简单的选项怎么样?

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

Sorry if I'm late to the party, and apologies too if this functionality has only been introduced in .NET 4, but the following is possible (now)抱歉,如果我迟到了,如果此功能仅在 .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

VB requires that the implementing property declare the implementation. VB 要求实现属性声明实现。 This is because of what I actually consider a nice feature of VB that I sometimes miss in C# -- that you can rename the member that implements the interface member.这是因为我实际上认为 VB 的一个很好的特性是我有时会在 C# 中错过——您可以重命名实现接口成员的成员。

Thus the only way to make this work without implementing IFoo.Description in FooBase is to declare Description Overridable and then define MyFoo as:因此,在FooBase不实现IFoo.Description的唯一方法是声明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

VB.NET does not support implicit implementation. VB.NET 不支持隐式实现。 I also ran into this issue and had a lot of trouble.我也遇到了这个问题,遇到了很多麻烦。

When you work with generated classes (entities etc.) where you have to explicitly declare Implements IFoo , it makes it impossible at all.当您使用生成的类(实体等)时,您必须显式声明Implements IFoo ,这根本不可能。

Therefore I submitted a connection to Microsoft and I hope you'll vote and next version of VB they will improve the compiler to be more clever.因此我向微软提交了一个连接,我希望你能投票,下一个版本的 VB 他们将改进编译器,使其更聪明。

I can't comment on MA Hanin's answer because of my rep, but I would recommend one small tweak to avoid compiler warnings about hiding base methods, assuming you don't want to or can't override override the property in the base class.由于我的代表,我无法对 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

This is a strange issue and it clearly shows a difference between the C# and VB.NET compilers.这是一个奇怪的问题,它清楚地显示了 C# 和 VB.NET 编译器之间的差异。 I would suggest that you do implement the interface on the abstract base class as this will make the VB.NET compiler happy and at execution time your child class will still have metadata indicating that it does in fact implement IFoo .我建议您确实在抽象基类上实现接口,因为这将使 VB.NET 编译器满意,并且在执行时您的子类仍将具有元数据,表明它确实实现了IFoo

Is there a specific reason that the child class must be the one to declare that it implements the interface?子类必须是声明它实现接口的那个,是否有特定的原因?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM