C# 2.0: get and set accessor can have different accessibility
One of the issues with properties in C#1.x is that the get and the set accessors get the same accessibility. In some situations you'd want to impose more usage restriction on the set accessor then on get . In the following sample both the get and set are public.
class Employee{ private string m_name; public string Name { get { return m_name; } set { m_name = value; } }}class Program{ static void Main(string[] args) { Employee emp = new Employee(); emp.Name = "Abhinaba Basu"; }}
In case you want set to be more restricted than get you have no direct way of getting it done in C#1.x (other than splitting them into different properties). In C# 2.0 its possible to have different accessibility on get and set accessors using accessor-modifier. The following code gives protected access to set and public to get
class Employee{ private string m_name; public string Name { get { return m_name; } protected set { m_name = value; } }}class Program{ static void Main(string[] args) { Employee emp = new Employee(); emp.Name = "Abhinaba Basu"; // Will fail to compile }}
This is really cool because in many designs I have felt the need to make set accessor protected and allow get to be internal or public. With this addition to C# this becomes easy to do.
There are however lot of gotchas and cases to consider before going ahead and blindly using this. I have listed some which I found need to be considered....
- Accessor-modifiers cannot be used in an interfaces or explicit interface implementation
- The modifier must be more restrictive than the accessibility of the property. So if the property is declared as protected then the modifier can only be private
- Accessor-modifier does not effect member lookup.
Be sure to check the C# spec before using this feature as there are some subtleties specially in terms of member lookup....
Comments
Anonymous
November 10, 2005
I've known about this feature for quite some time, but I still can't think of a good real-world example.
Do you have one I'm keen to see it.Anonymous
November 10, 2005
I used this capability a lot in my Java days. It was definitely nice to see it come over to C#.
Simon, there are many times where you want the world to be able to read a property, but not set it. The only time the value behind that property can be set is through other behaviors performed in that class. However, those behaviors will need to perform a common set of functionality whenever setting that value (i.e. checks). A logical place to put that is within a setter in a property. Previously in C# that would make the setter public since the getter was public. The workaround was to either duplicate the code or write it into a method.Anonymous
April 09, 2007
This is a good feature,...but what if the property is defined in the interface, and I want to give the get and set different accessors.How do I accomplish that, since the I can't define the accessor on the iterface?Anonymous
October 29, 2008
Interface members are always public. Therefore, to implement an interface that has properties whose accessors have mixed accessibility modifiers, you would simply leave the non-public accessors out of the interface declaration. For example... interface IPropAccessor { string SomeProperty { get; } } class PropImplementation : IPropAccessor { public string SomeProperty { get { ... } protected set { ... } } } The compiler is smart enough to figure out that the implicit implementation of IPropAccessor does not conflict with the declaration. If the setter in this case was public, then a compile-time error would be generated. Furthermore, if we attempt to set the SomeProperty property from outside of the PropImplementation class or one of its sub-classes, a compile-time error is generated because we have declared the setter protected. Just remember, interface members are always public even if the interface itself is not.Anonymous
October 29, 2008
Er.. Correction: Implementing a public accessor that is not included in the implicitly implemented interface is not considered an error. You just can't use that accessor through the interface. Going back to my previous example, it would not be a compile-time error to change the protected accessibility of the setter to public; however, it would be a compile-time error to attempt to set the SomeProperty value through the IPropAccessor interface.Anonymous
December 15, 2008
Hi I am new to C#. How would I use the set method after it has been protected in main and get the program compiled? Thanks ;)Anonymous
February 20, 2009
Really helpful information there, thank you Author. Keep up the good knowledge base =]Anonymous
July 08, 2009
Thanks mate. I knew that this functionality was possible but completely forgot how to do it.Anonymous
November 04, 2009
Correction: >>Furthermore, if we attempt to set the SomeProperty property from outside of the PropImplementation class or one of its sub-classes, a compile-time error is generated.
well, sub-classes (i.e. derived classes) can set the SomeProperty, since it is protected.