So I have a base class and there a property that is set to be [Serializable].
In the derived class I would like to make that property [NonSerialized].
How can this be done?
This would be a violation of OOP. The base class has established the fact that this property is serializable. It must be possible to substitute any instance of a derived class for an instance of the base class. This means that every instance of the derived class must have that property serializable.
You cannot substitute a new attribute, but you can define a property called ShouldSerializePropertyName (where PropertyName is the name of your property) that always returns false. This should override the presence of the attribute on the property.
For example,
public class BaseClass
{
[Serialized]
public string MyProperty { get; set; }
}
public class ChildClass : BaseClass
{
public bool ShouldSerializeMyProperty { get { return false; } }
}
Related
In a class I have a property
protected abstract string test{ get; }
When I try to initialize it in a constructor. I get an error saying:
Property or indexer xxx cannot be assigned to. -- it is read-only.
Is there a way to allow some property to be
abstract
Read-only after initialization in ctor ?
You likely don't want an abstract property. You would only use that if you wanted to force the derived class to provide a custom implementation. In your case you simply want it to be set in the constructor and readonly.
public abstract class Base
{
protected string MyProperty { get; }
public Base(string myProperty)
{
MyProperty = myProperty;
}
}
public class Derived : Base
{
public Derived()
: base("DefaultValue")
{ }
}
I have a class like this:
public class Base
{
public Base(string name)
{
this.Name = name;
}
public string Name { get; set; }
public string PrettyName
{
get { return Prettify(Name); }
}
}
and I derive from it:
public class Derived : Base
{
public Derived(Base b) : base(b.Name) { }
}
The Name property should not be accessed; the logical name should be accessed only by PrettyName. So I thought I'd make the property like this:
public string Name { protected get; set; }
But I'm getting this:
Cannot access protected member 'Name' via a qualifier of type 'Base'; the qualifier must be of type 'Derived' (or derived from it)
Why is that? The getter should be exposed to the base class and all its child classes. Am I getting something wrong here?
The getter should be exposed to the base class and all its child classes.
No, not quite. This isn't a matter of automatically implemented properties - it's a matter of what protected means.
Access to a protected member within a subclass has to be through an instance of that subclass (or a further subclass). You can't use Base.Name for an arbitrary Base in Derived.
From section 3.5.3 of the C# spec:
When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access must take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class.
A simple solution would be to overload the constructor in Base:
protected Base(Base b) : this(b.Name)
{
}
then in Derived:
public Derived(Base b) : base(b) { }
At that point, you can make the Name setter private, too - or better yet, make it fully read-only:
private readonly string name;
public string Name { get { return name; } }
That's a curious way of making the derived constructor. Why not:
public class Derived : Base
{
public Derived(string name) : base(name)
{ }
public void Test()
{
//here, it's perfectly ok to access the protected Name.
}
}
There's a fine question on overriding inherited attributes of properties.
Suppose an attribute:
[AttributeUsage(AttributeTargets.All, Inherited = true)]
public class MyAttributeAttribute : Attribute
//...
public class ParentClass
{
[MyAttribute]
public String MyString;
}
public class ChildClass : ParentClass
{
new public String MyString; //Doesn't have MyAttribute
}
But what if MyAttribute is set to a class?
[MyAttribute]
public class ParentClass
public class ChildClass; //Don't want MyAttribute
Is there a way to make ChildClass not inherit the attribute?
Context: Purely theoretical. I want to make an attribute inheritable and want to know, if the case happens some day, if I can override it.
You could copy the BrowsableAttribute approach mentioned in one of the answers to the question you reference. You can make a constructor with a boolean that when set to false will denote that the attribute, although present, should not be handled. You can also add a parameterless constructor that set the property to true. This is the one that you will use most often unless you decide to override the attribute inherited from a base class.
[AttributeUsage(AttributeTargets.All, Inherited = true)]
public class MyAttributeAttribute : Attribute
{
public bool Enabled { get; private set; }
public MyAttributeAttribute()
:this(true)
{
}
public MyAttributeAttribute(bool enabled)
{
Enabled = enabled;
}
}
Then when you reflect on your types and look for the attribute, you can check on the Enabled property and only if it is true you actually use it.
Your example class hierarchy will then be:
[MyAttribute]
public class ParentClass
[MyAttribute(false)]
public class ChildClass; //Don't want MyAttribute
Let's say I have a class which has a property hiding it's base property and a nested class inside this class. Is it possible to access the base hidden *virtual* property from the nested class?
Here is an example:
class BaseClass
{
protected virtual String SomeProperty {get; set;}
}
class Inherited : BaseClass
{
protected new String SomeProperty {get; set;}
class Nested
{
Inherited parent;
public Nested(Inherited parent)
{
this.parent = parent;
}
public void SomeMethod()
{
//How do I access the SomeProperty which belongs to the BaseClass?
}
}
}
The only solution that I can think of is to add a private method to Inherited class which returns base.SomeProperty Is there a better solution?
You could cast your InheritedClass reference to BaseClass. Since you hide the base property instead of overriding it, this should do the trick.
public void SomeMethod()
{
BaseClass baseRef = parent;
// do stuff with the base property:
baseRef.SomeProperty = someValue;
}
Edit:
To make this work, the SomeProperty property of the BaseClass has to be accessible to the nested class, either by making it internal (if you don't want to make the property accessible outside the declaring assembly) or protected internal (if you want to allow overriding in derived classes from other assemblies).
If both options are off limits (ie. when your derived class already is in another assembly), you won't get around declaring a wrapper property.
private string SomeBaseProperty
{
get
{
return base.SomeProperty;
}
set
{
base.SomeProperty = value;
}
}
In a base class, I want to define an abstract get, but at that point, I don't care about the set. How can I define a setter in my child class?
I tried a few things, but I can't get it to work. For example I tried :
public class BaseClass
{
public abstract bool MyBool { get; }
}
public class ChildClass : BaseClass
{
public override bool MyBool { get; protected set;}
}
And :
public class BaseClass
{
public bool MyBool { abstract get; }
}
public class ChildClass : BaseClass
{
public bool MyBool { override get; protected set;}
}
I know I can workaround this by not using automatic properties in the child class and directly setting the underlying field instead of creating a setter, but I'm looking for something better.
Edit: I don't want to add an abstract setter in the BaseClass.
It may make more sense to use an interface rather than a base class. Then you simply have the classes that need to provide that property implement that interface.
For instance, you can create this interface:
public interface IBoolable {
bool MyBool { get; }
}
Then it is still valid to implement the interface like so:
public class BoolableItem : IBoolable {
public bool MyBool { get; protected set; }
}
Done this way, your code can safely assume anything that implements IBoolable has a property called MyBool that is at minimum read-only.
One solution is to make MyProperty not abstract but delegate its implementation to an abstract protected property that children must override:
public abstract class BaseClass
{
public bool MyBool { get { return MyBoolInternal; } }
protected abstract bool MyBoolInternal { get; set; }
}
public class ChildClass : BaseClass
{
protected override bool MyBoolInternal { get; set; }
}
You have to make up your mind what behavior you want: if it is defined as abstract then a deriving class MUST implement it.
So what you should do is this:
public abstract class BaseClass
{
public abstract string MyProperty { get; set; }
}
public class DerivedClass : BaseClass
{
public override string MyProperty
{
get { return "myValue"; }
set { /* do nothing, not applicable for this class */ }
}
}
Don't throw the NotImplementedException - that is not what you want, you simply want the setter to do nothing for some child classes.
To leave it ambiguous whether you want a setter in inherited classes would violate OOP principles--that is, if a class (abstract or not) has a public/protected setter (abstract or not), then all inheriting classes must also; if a class does not, then inheriting classes must not.
Another way to think about this is to consider properties such that read-only or read-write is part of the contract of the class. Since instances of inheriting classes must adhere to an "Is-a relationship" (the LSP), inheriting classes cannot "add a setter" where the main class didn't have one, because the fact that the main class had a property without as setter is part of the main class definition. In effect, since the main class cannot change the property in question via a setter, therefore all inheriting classes MUST guarantee the same behavior.
Consider using a protected backing field; then you can split this property into a read-only property and a separate setter method. Then, the main class can have the property only and the subclass can have a setter method that the main class doesn't know about. However, I'm not sure this would be a good design either.