How to make a property protected AND internal in C#?
What's wrong with making the getter public? If you declare the property as
public string[] Headers { get; protected set; }
it meets all of the criteria you want: all members of the assembly can get the property, and only derived classes can set it. Sure, classes outside the assembly can get the property too. So?
If you genuinely need to expose the property within your assembly but not publicly, another way to do it is to create a different property:
protected string[] Headers { get; set; }
internal string[] I_Headers { get { return Headers; } }
Sure, it's ugly decorating the name with that I_
prefix. But it's kind of a weird design. Doing some kind of name mangling on the internal property is a way of reminding yourself (or other developers) that the property they're using is unorthodox. Also, if you later decide that mixing accessibility like this is not really the right solution to your problem, you'll know which properties to fix.
Property with internal set and protected get
Use internal
for the setter and protected internal
for the whole property.
public class X
{
// Read from this assembly OR child classes
// Write from this assembly
protected internal int Foo { internal set; get; }
}
The name protected internal
is a bit misleading, but does what you want to achieve:
A protected internal member is accessible from the current assembly or from types that are derived from the containing class.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/protected-internal
So, because the setter is internal
, you can set the property from anywhere in the same assembly but not from a different assembly. And because the property as a whole is protected internal
, you can read it from anywhere in the same assembly OR from child classes in any assembly.
Another approach:
public class X
{
// Read from child classes
// Write only from child classes in the same assembly
protected int Foo { private protected set; get; }
}
A private protected member is accessible by types derived from the containing class, but only within its containing assembly.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/private-protected
C# internal getter, protected setter with an internal class parameter
...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.
How to make a class member protected and internal?
All these answers are backwards: protected internal is available to derived classes OR other objects in the same (or InternalsVisibleTo) assembly. What you want is not possible and as Eric Lippert points out, not really useful, or at the least, something you shouldn't expect anytime soon: http://blogs.msdn.com/b/ericlippert/archive/2008/04/24/why-can-t-i-access-a-protected-member-from-a-derived-class-part-three.aspx
Using an internal type used as protected field
Create a public interface that MyAbstractClass
requires and MyInternalClass
implements.
Something like this so you can have it be MyInternalClass
by default but inject new behavior if you needed (for example, mocking):
internal class MyInternalClass : IMyInterface
{
}
public interface IMyInterface
{
}
public abstract class MyAbstractClass
{
protected IMyInterface myField;
protected MyAbstractClass(IMyInterface required = null)
{
myField = required ?? new MyInternalClass();
}
}
How to make a property protected AND internal in C#?
What's wrong with making the getter public? If you declare the property as
public string[] Headers { get; protected set; }
it meets all of the criteria you want: all members of the assembly can get the property, and only derived classes can set it. Sure, classes outside the assembly can get the property too. So?
If you genuinely need to expose the property within your assembly but not publicly, another way to do it is to create a different property:
protected string[] Headers { get; set; }
internal string[] I_Headers { get { return Headers; } }
Sure, it's ugly decorating the name with that I_
prefix. But it's kind of a weird design. Doing some kind of name mangling on the internal property is a way of reminding yourself (or other developers) that the property they're using is unorthodox. Also, if you later decide that mixing accessibility like this is not really the right solution to your problem, you'll know which properties to fix.
A tool to allow protected AND internal?
Since C# 7.2 there is construct private protected
(link) that does the job.
internal protected property still accessible from a different assembly
internal protected
means "internal to the assembly OR an inherited class". So yes, if you have a public class with an protected internal member, another class that inherits that type in a different assembly can still access it because of the protected modifier:
protected internal
The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly. Access from another assembly must take place within a class declaration that derives from the class in which the protected internal element is declared, and it must take place through an instance of the derived class type.
Reference: http://msdn.microsoft.com/en-us/library/ms173121.aspx
This is a limitation of the C# language. The CLR supports the "Internal AND Protected" notion. There is evidence of this with the MethodAttributes.FamANDAssem
enumeration if you were emitting your own IL. If you really wanted this feature, you could do some IL post processing with something like Mono.Cecil. Why the C# language does not expose this is only a guess: little need for it.
protected internal
C# does not have any such access modifier.
However, the CLR does support it, as the FamANDAssem access level (protected internal
is FamORAssem)
Related Topics
How to Write One to Many Query in Dapper.Net
Get Value of C# Dynamic Property via String
How to Implement Recaptcha for ASP.NET MVC
ASP.NET Identity Get All Roles of Logged in User
Selecting a Textbox Item in a Listbox Does Not Change the Selected Item of the Listbox
Cannot Convert Lambda Expression to Type 'System.Delegate'
How to Test If a Type Is Anonymous
Transitive References in .Net Core 1.1
How to Get the Line Number Which Threw Exception
How to Pronounce "=>" as Used in Lambda Expressions in .Net
C# Filestream:Optimal Buffer Size for Writing Large Files
Is There a Way of Setting a Property Once Only in C#
How to Receive Plug & Play Device Notifications Without a Windows Form