This property in a type with no access modifier (thus internal
access):
class SomeType {
private int length;
internal int Length {
get { return length; }
set length = value; }
}
}
allows all types within the assembly of SomeType to use get
and set
accessors. Problem: how to restrict the access to set
to only types derived from SomeType (and SomeType indeed)?
internal int Length {
get { return length; }
protected set length = value; }
}
is rejected by the compiler, because protected
is said to be less restrictive than internal
(supposedly: protected
has an intersection with internal
, but is not entirely included in internal
--> Derived types can exist beyond the scope of internal
).
What would be the code to have get accessed by any type within the assembly, and set only by derivated types within the assembly?
Edit: after reviewing the answers, I think I need to add another characteristic of the property, since it may make a difference in the solution: the type of the property is actually SomeType
. The edited code is:
class SomeType {
private SomeType length;
internal SomeType Length {
get { return length; }
set length = value; }
}
}
If the property is declared public
, then the compiler issues an error (the property type SomeType is less accessible the property Length).
(EDIT: I've just checked, and this works even when the type of the property is the same as the declaring type. However, it doesn't work when you're trying to declare a property within a public type where the type of the property is an internal type.)
You can't quite do that in C# (strictly speaking), but you can do something very similar:
protected internal int Length { get; protected set; }
(This is using an automatically implemented property just for simplicity; the same technique would work for a "normal" property too.)
This will make the "getter" accessible to any type within the same assembly and derived types; the "setter" will only be accessible to derived types. As your class is internal anyway, this is pretty much equivalent anyway - the getter would theoretically be accessible to types outside the assembly, but as the class is internal, nothing from a different assembly should be deriving from your type anyway.
The problem is that properties require that one access level is a "subset" of the other; internal
and protected
don't work like that - one type can be in the same assembly but not derived from the type in question; another type can be derived from it but in a different assembly. They're orthogonal, basically.
The above solution works because protected internal
means it's accessible to any type which is either in the same assembly or derived from the type. Clearly each of protected
and internal
individually is a subset of this.
You would be able to make an internal
property which was further restricted for the setter if C# had some equivalent to the CLR "family and assembly" access level. (protected internal
is equivalent to "family or assembly".) Unfortunately for you, it doesn't :(
If you really want the originally stated goals (e.g. if you later have a public class you want to apply the same restrictions to), you'll have to make at least one of them a separate method instead, e.g.
private int length;
internal int Length { get { return length; } }
protected void SetLength(int value)
{
this.length = value;
}