8
votes

I was having the problem of wanting a property to have an internal getter and a protected setter, as described in this question, and I thought I solved that by doing the following:

public class Accessor : AccessorBase
{
    private Connection _connection;

    protected void setConnection(Connection value)
    {
        _connection = value;
    }

    internal Connection GetConnection()
    {
        return _connection;
    }
    ...
}

However, I'm now getting this error:

Inconsistent accessibility: parameter type 'Connection' is less accessible than method 'setConnection(Connection)'

This is because I have internal class Connection. I would rather not make Connection a public class, while Accessor needs to be public, so how can I get around this error while still maintaining an internal getter and a protected setter?

7

7 Answers

10
votes

Unfortunately C# doesn't support "internal and protected" access modifiers (only "internal or protected" is supported), which means any protected members are visible outside the assembly and can't use an internal type.
Using internal instead of protected would be the most logical solution.

And you could vote at Microsoft Connect so that it might be added to C# someday.

Update: as of C# 7.2 you can use private protected for this.

5
votes

Create a public interface IConnection that your internal Connection object implements. Have your GetConnection and SetConnection methods accept and return IConnection instead of Connection.

Basic SOLID principles win again.

2
votes

...any protected members are visible outside the assembly and can't use an internal type.

-- Pent Ploompuu's answer

One way of getting around this is to make Connection public while making all its instance methods and constructors internal.

1
votes

If the class Connection is internal, a class deriving Accessor won't be able to call protected setConnection since it doesn't have access to Connection.

If setConnection is to be protected, Connection will have to be public.

0
votes

Sorry, If you need that exact setup, you'll need to make your Connection class public.

0
votes

Unfourtanly you cannot do that. Since the Connection is internal some class deriving from Accessor from another assembly would not be able to see Connection, even if you mark the setter as protected internal it would solve nothing.

Your only hope is to make the class Connection public.

0
votes

Coincoin is correct, Accessor is a public class anyone can derive from it, this means from a different assembly as well. That derived class now has protected method to which you need to pass an internal (from another assembly) class. This would never work.

You need to either make Accessor internal or Connection public, or better yet follow Randolphos answer

Here is a code example of the problem

Assembly 1

//this class is only visible in Assembly 1
internal class Connection
{

}
public class Accessor
{
   protected void SetConnection(Connection con) { }
}

Assembly 2 - has reference to Assembly 1

//possible because Accessor is public
DerivedAccessor : Accessor
{
   void SomeMethod()
    {
        this.SetConnection(????) // you can't pass Connection, its not visible to Assembly2 
    }
}