I have a base class and a derived class. Each has the same property which has a private setter so the value can be set by some logic inside the class.
class First
{
internal virtual int Value { get; private set; }
void SetValue(int toValue)
{
Value = toValue;
}
}
class Second : First
{
internal override int Value { get; private set; }
void SetValue(int toValue)
{
Value = toValue;
}
}
This is resulting in a compiler error:
The property or indexer ... cannot be used in this context because the
set accessor is inaccessible.
Why is that the case, and how can I achieve what I'm trying to do? Is this not possible with auto-implemented properties, in other words, do I have to use a backing field instead?
Second would be unable to set the value of Value from First due to Values setter being private. If you need your subclass to be able to set it, it needs to be protected in the base.
Getters and Setters are basically methods. You can't override methods you can't see. The virtual in this case only applies to the getter as virtual private is not allowable.
It's not just that you can't see it to use it, you cannot override it at all.
Related
For proper encapsulation, should I use a private property with a manual getter method like in Java:
public class Foo {
private int Prop { get; set; }
public Foo
{
Prop = 1;
}
public int GetProp()
{
return Prop;
}
}
Or should I simply use a public property?
public class Foo {
public int Prop { get; private set; }
public Foo
{
Prop = 1;
}
}
Properties are the way of creating getters and setters in C#, so there is no reason to create a getter method, like you would in Java.
In other words: You should use the second example.
Typically the proper way to do this is:
private int prop;
public int Prop
{
get { return prop; }
set { prop = value; } //do other stuff within set if needed.
}
This way you have access to everything, but can still do something custom (commonly NotifyPropertyChanged) if needed.
A property is just a syntactic sugar for get_PropertyName and set_PropertyName methods in c#.
public class Foo
{
public int Prop { get; private set; }
}
Is equivalent to:
public class Foo
{
private int _prop;
private void set_prop(int value) { _prop = value; }
public int get_prop() { return _prop; }
}
It's best that you use auto properties when possible and use properties with backing fields when you need to add logic to the getter/setter of individual fields.
If the property is going to be private, as it is in your first example, you should just use a field.
The point of a Property is usually that you have a get and set function, that can be used mostly like a variable. Your first example is really wierd - why not just make the getter only public? Readonly and Writeonly properties are not a uncommon sight:
//Public property with private get or writeonly
public int Prop { private get; set; }
//Readonyl property
public int Prop { get; private set; }
One important rule regarding the Backing field: It is very important that you do not mix up the Property and it's backing field, especially in class code. If you use Autoimplement Properties, that danger is non-existant. If your code is more complex than that, a common approach is to append a underscore (_) to the backing field name. Prop/prop is too easy to mix up. _Prop and Prop are really hard to mix up ,especialyl for autocompletion features.
In general, methods represent actions and properties represent data. While both your examples can be used identically, the 'proper' way of representing state is through properties, and using properties correctly tells consumers of your object that this is representing state, not an action.
You should also consider how things like serialization and intellisense are expecting properties instead of methods.
I'm a bit confused with encapsulation of properties setter in base class.
Supposing some of those properties are set in base constructor, the setter should be private or protected ?
Supposing some of those properties are set in child constructor, the setter should be private or protected ?
In order to be clearer, here is a concrete case :
public abstract class Records
{
public string Date { get; protected set; }
public string Source { get; protected set; }
public string Type { get; protected set; }
public int Value { get; protected set; }
protected Records(string type, string source, int value)
{
Type = type;
Source = source;
Value = value;
Date = DateTime.Now.ToString("hh.mm.ss.ffffff");
}
}
public class NewDocumentRecord : Records
{
public NewDocumentRecord(string source, int value)
: base(ContentTypesString.DocumentNew, source, value)
{
Source = source;
Value = value;
}
}
Generally, it is very hard to make a case for a protected setter in the base class: if a property belongs in the base class, the logic that controls it belongs in the base class as well.
Supposing some of those properties are set in base constructor, the setter should be private or protected?
Assuming that the property is set once in the constructor, and never changes again, the setter should be private, or there should be no setter at all (C# 6 or later).
public string Date { get; }
Supposing some of those properties are set in child constructor, the setter should be private or protected?
If the property is declared in the base class, the task of setting its initial value should be part of base class constructor as well. The best course of action is to pass the value from child constructor to base constructor, letting it validate the data prior to setting the value into the property.
This does not mean that you should never let subclasses modify properties declared in the base class, only that you should avoid making auto-generated setters protected. If you need to make a property modifiable only by subclasses, provide them a protected method to do so.
If you wannna set property only in base class and hide it from children classes you should make setter private.
If you wanna set value only in base ahd children classes you should make it protected.
I have this code:
public string foo { get; set; }
Now, I interpret this as my object has a public property called foo, and both it's accessor's are public. If I write this:
private string foo { get; set; }
I interpret that as my object has a private property called foo, and both it's accessor's are private. I understand making the property itself private. What I don't understand is why the accessor's must be more restrictive? If I write:
private string foo { public get; public set; }
I interpret that my object has a private property called foo, and both's it's accessor's are public, which is the behavior that I want. I'd like the private property with public accessors. I mean, if I have to write a Get/Set method, I will. But I'm just confused as to why this is.
A property is actually (under water) nothing more than two methods:
public string foo { get; set; }
will translate into:
public string get_foo() { ... }
public void set_foo(string value) { ... }
These methods can only have ONE access modifier, not a combination of two.
If I remember correcly, C#v1 did not support access modifiers for the getters and setters. There was one access modifers for the property which was used for both functions.
In v2 it was possible to "override" one of getter/setter-pair, this way overrwriting the "other" function. There was no use to override both getters/setters, because in that would render the property-access modifier useless.
Why the access modifier for the getter/setter is more restrictive has, in my opinion, something to do with easier implementing interfaces which always have (implicitly public) properties.
For more info, read: http://msdn.microsoft.com/en-us/library/75e8y5dd(v=vs.80).aspx
Why you need such a property
private string foo { public get; public set; }
If you want to have you get set public, then make the property public.
The compiler will first check the access of the property and then its method. If the property is public then its method can have either public or private or any accessor
Can we have different access modifier for get and set in a property?
Yes, you can, however it is subject to the rule that your getter/setter cannot have a less restricted access modifier than the property itself.
For example (C#):
public Foo { get; private set; } //this is okay
protected Bar { get; public set; } //this will throw a compile error
You can restrict the getter or setter of a property:
public string MyProperty
{
get { return _myProperty; }
private set { _myProperty = value; }
}
It also works with internal and protected. However, the key word here is "restrict" - you can't make either modifier more accessible than the overall modifier.
I have a situation like this:
public abstract class BaseClass
{
public abstract string MyProp { get; }
}
Now, for some of the derived classes, the properties value is a synthesized values, so there is no setter:
public class Derived1 : BaseClass
{
public override string MyProp { get { return "no backing store"; } }
}
This works fine. However, some of the derived class required a more traditional backing store. But, no matter how I write it, as on automatic property, or with an explicit backing store, I get an error:
public class Derived2 : BaseClass
{
public override string MyProp { get; private set;}
}
public class Derived3 : BaseClass
{
private string myProp;
public override string MyProp
{
get { return myProp;}
private set { myProp = value;}
}
}
Derived2.MyProp.set': cannot override because 'BaseClass.MyProp' does not have an overridable set accessor
How do I get this to work??
The best thing you can do is implement the property as virtual instead of abstract. Make the get and set blocks for each throw NotSupportedException in the base class and override the behaviour accordingly in derived classes:
public virtual string MyProp {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
Basically, you cannot. By adding a setter you are changing the definition of the property, so it does not really "override" the base property. It's the same as if you tried to override a method and add another parameter to it - they would be treated as different methods (overloaded). Since properties cannot be overloaded this won't work.
You'll just have to add another method to set the value (perhaps with protected accessibility).
Bradley's suggestion is good, but one thing I've done in cases where only the Setter should be virtual is to do something this this:
public class Root
{
private string _MyProp;
public string MyProp
{
get { return _MyProp;}
set { _MyProp = SetMyProp(value); }
}
protected virtual string SetMyProp(string suggestedValue)
{
return suggestedValue;
}
}
public class Child
: Root
{
protected override string SetMyProp(string suggestedValue)
{
string oReturn = base.SetMyProp(suggestedValue);
// Do some sort of cleanup here?
return oReturn;
}
}
It requires a little extra work up front, but it seems to maintain a higher degree of encapsulation (e.g. you can prevent subclasses from overriding the Getter behavior, and your subclass doesn't have to be aware of the underlying member behind the property).
I would suggest avoiding virtual or abstract properties. Instead, use a non-virtual property which chains to protected virtual or abstract get/set methods. Doing that will allow derived classes to override the methods and also shadow the property with one that has different access modifiers. Since the base property itself will be non-virtual, there will never be any need to override it, so the naming conflict with the new version won't matter.