无法实现接口成员,因为它不是公共的

时间:2014-02-20 05:20:57

标签: c#

我写了一些VB代码,我使用Sharp Develop IDE转换为C#。 我定义了一个接口IElement,它由返回自身XML表示的对象实现。实现此接口的任何对象都应该能够返回其TagName及其XML字符串表示形式。要获取它的XML字符串,它可能必须遍历其子/嵌套集合以获取其所有子对象的XML表示。

从Element继承的类可以使用其基类的GetXml和GetNestedXml,或者选择覆盖它,但GetNestedXml函数不需要是公共的,因为它只能从派生类的公共GetXml函数调用。因此,在原始VB版本中,GetNestedXML的范围设置为protected。但是,Sharp Develop和我在尝试将此代码转换为C#时遇到了问题。请参阅下面的错误。

另一方面,我确实意识到可能有更好的方法来实现这一点,我会对易于火上浇油的方面建议感兴趣。 :-)谢谢。

Public Interface IElement

    ReadOnly Property TagName() As String
    ReadOnly Property GetXml(Optional ByVal targetXml As Integer = TargetXmlEnum.All) As String
    Function GetNestedXml() As String

End Interface


Public Class Element

    Implements IElement

    Public ReadOnly Property TagName() As String Implements IElement.TagName
        Get
            '....
        End Get
    End Property

     Public Overridable ReadOnly Property GetXml(Optional ByVal targetXml As Integer = TargetXmlEnum.All) _
            As String Implements IElement.GetXml
        Get
            '....
        End Get
    End Property

    Protected Overridable Function GetNestedXml() As String Implements IElement.GetNestedXml
        '....
    End Function

End Class

转换后的C#:

public interface IElement
{

    string TagName { get; }
    string GetXml { get; }
    string GetNestedXml();

}

public class Element : IElement
{
    public string TagName {
        get { //... }
    }

    public virtual string GetXml 
    {
        get 
        {
            //...
        }
    }

    protected virtual string GetNestedXml()
    {
        //...
    }
}

错误:

Error   1   'Smit.SpreadsheetML.Element' does not implement interface member 'Smit.SpreadsheetML.IElement.GetNestedXml()'. 'Smit.SpreadsheetML.Element.GetNestedXml()' cannot implement an interface member because it is not public.   D:\Users\Chad\Desktop\SMIT\SMIT.SpreadsheetML.ConvertedToC#\Element.cs  41  24  Smit.SpreadsheetML.Converted

4 个答案:

答案 0 :(得分:4)

由于接口实现需要公开或明确:

更改此方法

protected virtual string GetNestedXml()
{
     //...
}

protected virtual string IElement.GetNestedXml()
{
    //...
}

修改

创建一个这样的界面:

public interface IElement
{
    string TagName { get; }
    string GetXml { get; }
}

像这样创建一个抽象基类

abstract class ElementBase:IElement

{
    public abstract string TagName { get; }
    public abstract string GetXml { get; }
    protected abstract string GetNestedXml();
}

阻止你的元素类

public class Element : ElementBase
{
    public override string TagName {
        get { //... }
    }

    public override string GetXml 
    {
        get 
        {
            //...
        }
    }

    protected override string GetNestedXml()
    {
        //...
    }
}

答案 1 :(得分:3)

接口声明了其所有继承实例的职责。因此,您不能使用非公共方法来实现您的接口方法。

如果由于其他原因它是非公开的,我建议您可以使用抽象类并使用抽象/虚方法来声明它。

像这样的抽象方法:

public interface IElement
{
    string TagName { get; }
    string GetXml { get; }
}

public abstract class ElementBase : IElement
{
    public string TagName { get; private set; }
    public string GetXml { get; private set; }
    protected abstract string GetNestedXml();
}

虚拟方法:

public interface IElement
{
    string TagName { get; }
    string GetXml { get; }
}

public abstract class ElementBase : IElement
{
    public string TagName { get; private set; }
    public string GetXml { get; private set; }

    protected virtual string GetNestedXml()
    {
        throw new NotImplementedException();
    }
}

答案 2 :(得分:1)

解决此问题的快捷方法是将GetNestedXml公开。如果您不想这样做,您还可以将GetNestedXml声明为抽象基类中的受保护抽象方法。但这意味着所有类都需要从这个基类派生并实现该方法。如果要在基类中提供实现,还可以将方法设置为虚拟,以便派生类可以但不一定需要覆盖它。为此,请执行以下步骤:

  1. 创建一个新的抽象基类。
  2. 添加GetNestedXml()的受保护的抽象/虚拟实现。如果它是虚拟的,还提供一个方法体(并且您不需要使该类抽象)。
  3. 从界面中删除该方法。
  4. 从基类派生所有实现该接口的类(并希望获得基本实现GetNestedXml的舒适性)。
  5. 隐藏方法的另一种方法是显式实现IElement,以便调用者只有在使用接口访问对象时才能看到它。

答案 3 :(得分:0)

问题是,当您声明Element实现IElement时,您说:“嘿,我知道如何获取嵌套的XML,并且每个人都可以使用它!(公共......) ”

在课堂上GetNestedXml受到保护,即您没有履行声明 即使你做了明确的protected实现:

    protected override string IElement.GetNestedXml()
    {
       //Implementation...
    }

在幕后,它实际上仍然是be public