实现从 C# 到 VB.NET 的接口

Implementing Interface from C# to VB.NET

我下载了一个 C# 项目并想在 VB.Net 上工作,所以我决定将其从 C# 转换为 VB.NET,但在实现接口时遇到了一些问题。关于如何必须具有 Read-OnlyWrite-Only 说明符的实现,我一直在 VB.NET 中收到错误。我想摆脱这个错误,但我不知道如何实现。

我有三个文件:

  1. CustomPaintRichText.vb
  2. IUnderlineableSpellingControl.vb
  3. ISpellingControl.vb

C# 也是如此,但是在 C# 中它工作正常,我想尝试让它像在 VB.net 中那样工作。

CustomPaintRichText.vb:

Public Class CustomPaintRichText
Inherits RichTextBox
Implements IUnderlineableSpellingControl

Public m_underlinedSections As Dictionary(Of Integer, Integer)
Public m_protectedSections As Dictionary(Of Integer, Integer)
Public m_ignoredSections As Dictionary(Of Integer, Integer)
Public Property UnderlinedSections() As Dictionary(Of Integer, Integer)
    Get
        If m_underlinedSections Is Nothing Then
            m_underlinedSections = New Dictionary(Of Integer, Integer)()
        End If
        Return m_underlinedSections
    End Get
    Set(value As Dictionary(Of Integer, Integer))
        m_underlinedSections = value
    End Set
End Property

Public WriteOnly Property ProtectedSections() As Dictionary(Of Integer, Integer)
    Set(value As Dictionary(Of Integer, Integer))
        m_protectedSections = value
    End Set
End Property

Public WriteOnly Property IgnoredSections() As Dictionary(Of Integer, Integer)
    Set(value As Dictionary(Of Integer, Integer))
        m_ignoredSections = value
    End Set
End Property

Private spellingEnabled As Boolean
Private spellingAutoEnabled As Boolean
Private m_isPassWordProtected As Boolean

Private penColour As Pen
Public Property WhatPenColour() As Pen
    Get
        Return penColour
    End Get
    Set(value As Pen)
        penColour = value
    End Set
End Property

Public Property IsSpellingEnabled() As Boolean
    Get
        Return spellingEnabled
    End Get
    Set(value As Boolean)
        spellingEnabled = value
    End Set
End Property

Public Property IsSpellingAutoEnabled() As Boolean
    Get
        Return spellingAutoEnabled
    End Get
    Set(value As Boolean)
        spellingAutoEnabled = value
        If Not spellingEnabled Then
            spellingEnabled = value
        End If
    End Set
End Property

Public Property IsPassWordProtected() As Boolean
    Get
        Return m_isPassWordProtected
    End Get
    Set(value As Boolean)
        m_isPassWordProtected = value
    End Set
End Property
End Class

IUnderlineableSpellingControl.vb:

Public Interface IUnderlineableSpellingControl
   Inherits ISpellingControl
   Inherits IUnderlineable
End Interface

ISpellingControl.vb:

Public Interface ISpellingControl
<Browsable(True)> _
Property IsSpellingEnabled() As Boolean
Property SelectionStart() As Integer
Property SelectionLength() As Integer
Property SelectedText() As String
Property Text() As String
Property ContextMenuStrip() As ContextMenuStrip
Property WhatPenColour() As Pen
Property Parent() As Control
Event Disposed As EventHandler
Event Enter As EventHandler
Event TextChanged As EventHandler
Property [ReadOnly]() As Boolean
ReadOnly Property IsPassWordProtected() As Boolean
Sub Cut()
Sub Copy()
Sub Paste(clipFormat As DataFormats.Format)
Sub [Select](start As Integer, length As Integer)
Function Focus() As Boolean
Sub Invalidate(invalidateChildren As Boolean)
WriteOnly Property IgnoredSections() As Dictionary(Of Integer, Integer)
End Interface

如果我将光标保持在 Implements IUnderlineableSpellingControl 旁边并按 ENTER 键,在 CustomPaintRichText.vb class 内,我得到:

Public Property ContextMenuStrip1 As ContextMenuStrip Implements ISpellingControl.ContextMenuStrip

Public Sub Copy1() Implements ISpellingControl.Copy

End Sub

Public Sub Cut1() Implements ISpellingControl.Cut

End Sub

Public Event Disposed1(sender As Object, e As EventArgs) Implements ISpellingControl.Disposed

Public Event Enter1(sender As Object, e As EventArgs) Implements ISpellingControl.Enter

Public Function Focus1() As Boolean Implements ISpellingControl.Focus

End Function

Public WriteOnly Property IgnoredSections1 As Dictionary(Of Integer, Integer) Implements ISpellingControl.IgnoredSections
    Set(value As Dictionary(Of Integer, Integer))

    End Set
End Property

Public Sub Invalidate1(invalidateChildren As Boolean) Implements ISpellingControl.Invalidate

End Sub

Public ReadOnly Property IsPassWordProtected1 As Boolean Implements ISpellingControl.IsPassWordProtected
    Get

    End Get
End Property

Public Property IsSpellingEnabled1 As Boolean Implements ISpellingControl.IsSpellingEnabled

Public Property Parent1 As Control Implements ISpellingControl.Parent

Public Sub Paste1(clipFormat As DataFormats.Format) Implements ISpellingControl.Paste

End Sub

Public Property ReadOnly1 As Boolean Implements ISpellingControl.ReadOnly

Public Sub Select1(start As Integer, length As Integer) Implements ISpellingControl.Select

End Sub

Public Property SelectedText1 As String Implements ISpellingControl.SelectedText

Public Property SelectionLength1 As Integer Implements ISpellingControl.SelectionLength

Public Property SelectionStart1 As Integer Implements ISpellingControl.SelectionStart

Public Property Text1 As String Implements ISpellingControl.Text

Public Event TextChanged1(sender As Object, e As EventArgs) Implements ISpellingControl.TextChanged

Public Property WhatPenColour1 As Pen Implements ISpellingControl.WhatPenColour

Public Sub CustomPaint1() Implements IUnderlineable.CustomPaint

End Sub

Public Property IsSpellingAutoEnabled1 As Boolean Implements IUnderlineable.IsSpellingAutoEnabled

Public Event KeyDown1(sender As Object, e As KeyEventArgs) Implements IUnderlineable.KeyDown

Public WriteOnly Property ProtectedSections1 As Dictionary(Of Integer, Integer) Implements IUnderlineable.ProtectedSections
    Set(value As Dictionary(Of Integer, Integer))

    End Set
End Property

Public Sub RemoveWordFromUnderliningList1(wordStart As Integer) Implements IUnderlineable.RemoveWordFromUnderliningList

End Sub

Public Event SelectionChanged1(sender As Object, e As EventArgs) Implements IUnderlineable.SelectionChanged

Public Property UnderlinedSections1 As Dictionary(Of Integer, Integer) Implements IUnderlineable.UnderlinedSections

当我从表单对 CustomPaintRichText 进行更改时,我将拥有额外的附加控件,但最终没有任何效果。

错误Implements IUnderlineableSpellingControl中。下划线表示:'CustomPaintRichText' 必须为接口 'ISpellingControl' 实现 'Event Disposed(sender As Object, e As System.EventArgs)'。这是 30 个错误之一,还有 ..must implement..for 接口。

如果您想查看我收到的错误类型,请点击此处 error list

以下是 .cs 文件,以防:

  1. CustomPaintRichText.cs
  2. IUnderlineableSpellingControl.cs
  3. ISpellingControl.cs

C# 允许您使用 read/write 属性 实现 WriteOnly 或 ReadOnly 属性。 (VB 2015 也允许这样做)。 您可以在 VB 2015 年之前轻松解决此问题 - 以下是您的 IsPasswordProtected 实施示例:

Private ReadOnly Property ISpellingControl_IsPassWordProtected() As Boolean Implements ISpellingControl.IsPassWordProtected
    Get
        Return IsPassWordProtected
    End Get
End Property
Public Property IsPassWordProtected() As Boolean
    Get
        Return isPassWordProtected_Renamed
    End Get
    Set(ByVal value As Boolean)
        isPassWordProtected_Renamed = value
    End Set
End Property

'Implements' 继续调用现有的 read/write 属性.

的新 ReadOnly 属性

恭喜,你让 Hans Passant 走了 "Ugh!" :)

不过,说到他的观点,在 .NET 世界中通常鼓励混合和匹配从 VB、C#、C++/CLI、F# 或其他语言编译的程序集,并且是实用的解决方案你的问题。但是,如果您坚持将此 C# 项目转换为其 VB 等价项目,则需要了解这两种语言在接口实现方式方面的差异。

C# 有两种实现方式:隐式和显式(参见 http://blogs.msdn.com/b/mhop/archive/2006/12/12/implicit-and-explicit-interface-implementations.aspx). VB has only an explicit style, which doesn't work quite the same as C# (see https://msdn.microsoft.com/en-us/library/28e2e18x.aspx)。

所有这些 "must implement" 错误的意思与他们所说的差不多:您必须在子 class 的适当成员上使用 Implements 关键字,因为 VB不做接口的隐式实现。那是 C# 的东西。当您使用 Implements IUnderlineableSpellingControl 旁边的光标插入符按下 ENTER 键时,IDE 会为受影响的(显然缺失的)成员生成模板代码,并以 Implements 完成。它这样做是为了提供帮助,但在这种情况下,您必须查看代码并在需要的地方放入 Implements 子句(并且可能会删除该模板代码)。

C# 有一种简洁的隐式风格,它会通过匹配 class 和正在实现的接口之间的成员名称自动 "wire-up" 实现。如果有多个接口具有相同的成员(具有相同的签名),它们将在您的 class 中用完全相同的成员实现(参见 http://blogs.msdn.com/b/mhop/archive/2006/12/12/implicit-and-explicit-interface-implementations.aspx)。根据情况,这可能是一件好事,也可能不是一件好事。

C# 的显式风格有限。只需以 InterfaceName.MemberName 的格式在命名中定义一个成员(参见 https://msdn.microsoft.com/en-us/library/ms173157.aspx)。

VB 只有它的显式风格,但它允许在 Implements 子句中列出接口成员,以便它们都由 [=39= 中的同一个成员实现].这是连接多个接口的 C# 隐式实现的解决方法。

最后,有一些消息来源声称 VB 不能在已经实现的 superclass 的 subclass 上重新实现接口(例如http://www.dotnetheaven.com/article/how-to-re-implement-interfaces-in-vb.net)。我不知道这是否是真的,但我可以断言 VS 2012 的 VB 及更高版本允许此类重新实现。