Chad
Chad

Reputation: 24679

Cannot implement an interface member because it is not public

I wrote some VB code that I converted to C# using Sharp Develop IDE. I defined an Interface, IElement, that is implemented by objects that return XML representations of themselves. Any object that implements this interface should be able to return its TagName and it's XML string representation. To get the it's XML string, it may have to loop through its child/nested collection to get the XML representation of all of its child objects.

Classes that inherit from Element can use the GetXml and GetNestedXml of its base class or choose to override it but the GetNestedXml function would not need to be public because it would only be called from the public GetXml function of derived classes. Therefore, in the original VB version, the scope of the GetNestedXML was set to protected. However, Sharp Develop and I have issues trying to convert this code to C#. Please see the error below.

On a side note, I do realize that there might be better ways to implement this and I would be interested in side suggestions that are easy on flames. :-) Thanks.

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

Converted 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:

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

Upvotes: 7

Views: 16675

Answers (4)

Avi Turner
Avi Turner

Reputation: 10456

The thing is, that when you declare Element implements IElement you say: "Hey, I know how to get my nested XML, and every one can use it! (public...)".

On your class the GetNestedXml is protected, i.e. you are not fulfilling your declaration.
Even if you do an explicit protected implementation:

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

Behind the scenes, It will still actually be public.

Upvotes: 0

workingbird
workingbird

Reputation: 77

An interface declared the responsibilities of its all inheriting instances. So you can not use not-public method to implement your interface method.

If it is non-public for any reason else, I suggest that you can use abstract class and use a abstract/virtual method to declare it.

abstract method like this:

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();
}

virtual method:

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();
    }
}

Upvotes: 3

Saghir A. Khatri
Saghir A. Khatri

Reputation: 3128

As Interface implementations need to be public or explicit:

change this method

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

to

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

Edit

create an Interface like this:

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

create an abstract base class like this

abstract class ElementBase:IElement

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

Impelement your Element class

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

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

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

Upvotes: 5

Markus
Markus

Reputation: 22456

The quick way to solve this is to make GetNestedXml public. If you don't want this, you can also declare GetNestedXml as a protected abstract method in an abstract base class. But this means that all classes need to derive from this base class and implement the method. If you want to provide an implementation in the base class, you can also make the method virtual so that the derived classes can but do not necessarily need to override it. In order to achieve this, perform the following steps:

  1. Create a new abstract base class.
  2. Add a protected abstract/virtual implementation of GetNestedXml(). If it is virtual, also provide a method body (and you do not need to make the class abstract).
  3. Remove the method from the interface.
  4. Derive all classes that implement the interface (and want to have the comfort of the basic implementation GetNestedXml) from the base class.

Another way to hide the method would be to implement IElement explicitly, so that the the callers only see it when they access the object using the interface.

Upvotes: 1

Related Questions