How to have the base class be aware of derived class properties? - c#

I'm trying to create a base class that will be used in storing data in key/value manner. The base class will generate the keys and is responsible for storing the data. When the base class is inherited, the derived class can specify it's own key but the the base class has to be aware of the derived classes' key. For example:
public class ParentClass
{
private string key = "Parent";
public void GenerateKey()
{
Console.WriteLine(key);
}
}
public class FeatureClass : ParentClass
{
public string key = "Feature";
}
public class SubFeatureClass : FeatureClass
{
public string key = "SubFeature";
}
FeatureClass feature = new FeatureClass();
feature.GenerateKey(); //I would like this to produce "Parent_Feature"
SubFeatureClass subFeature = new SubFeatureClass();
subFeatureClass.GenerateKey(); //I would like this to generate "Parent_Feature_SubFeature"
How can I make the base class be aware of its children's keys regardless of how many levels of inheritance has occurred.

You can do this by making the base method virtual and referencing it in the override:
public class ParentClass
{
public virtual string key {get {return "Parent";}}
public void GenerateKey()
{
Console.WriteLine(key);
}
}
public class FeatureClass : ParentClass
{
public override string key {get{return base.key + "_Feature";}}
}
public class SubFeatureClass : FeatureClass
{
public override string key {get{return base.key + "_SubFeature";}}
}

You could do this, using virtual properties,
public class ParentClass
{
public virtual string Key
{
get
{
return "Parent";
}
}
}
public class FeatureClass : ParentClass
{
public override string Key
{
get
{
return base.Key + "_" + "Feature";
}
}
}
public class SubFeatureClass : FeatureClass
{
public override string Key
{
get
{
return base.Key + "_" + "SubFeature";
}
}
}
Then, you could use it this way,
FeatureClass feature = new FeatureClass();
Console.WriteLine(feature.Key); // <-- "Parent_Feature"
SubFeatureClass subFeature = new SubFeatureClass();
Console.WriteLine(subFeature.Key); // <-- "Parent_Feature_SubFeature"

Use a virtual property instead of a field:
public class ParentClass
{
public ParentClass(){Key = "Parent";}
private virtual string Key {get;set;}
public void GenerateKey()
{
Console.WriteLine(Key);
}
}
public class FeatureClass : ParentClass
{
public FeatureClass(){Key = base.Key + "_" + "Feature";}
override string Key {get;set;}
}

public class ParentClass
{
protected List<string> keys = new List<string>();
public ParentClass()
{
keys.Add("Parent");
}
public void GenerateKey()
{
Console.WriteLine(string.Join("_", keys));
}
}
public class FeatureClass : ParentClass
{
public FeatureClass()
{
keys.Add("Feature");
}
}
public class SubFeatureClass : FeatureClass
{
public SubFeatureClass()
{
keys.Add("SubFeature");
}
}

Abstract or virtual functions can be used to achieve this (which one depends on whether it makes sense for ParentClass to be the actual type or whether it always needs a derived class.
In any case, you would have a virtual (or abstract) function which you override in the derived class to return the special key. In fact, in C# you can have virtual/abstract properties:
public abstract class ParentClass
{
private string key = "Parent";
protected abstract string derivedKey
{
get;
}
public void GenerateKey()
{
Console.WriteLine(key + derivedKey);
}
}
public class FeatureClass : ParentClass
{
public override string derivedKey
{
get
{
return "Feature";
}
}
}

Using constructor overloading and constructor chaining in my version:
public class ParentClass
{
private string key;
protected ParentClass(string childKeys)
{
key = !string.IsNullOrEmpty(childKeys) ? key + "Parent_" + childKeys : key;
}
public void GenerateKey()
{
// Get keys from subclasses
Console.WriteLine(key);
}
}
public class FeatureClass : ParentClass
{
public FeatureClass() : base("Feature") { }
protected FeatureClass(string key) : base("Feature_" + key) { }
}
public class SubFeatureClass : FeatureClass
{
public SubFeatureClass() : base("SubFeature") { }
protected SubFeatureClass(string key) : base("SubFeature_" + key) { }
}
public class ReallySubFeatureClass : SubFeatureClass
{
public ReallySubFeatureClass() : base("ReallySubFeature") { }
}
Test code looks just like yours but I added one more level for example:
class Program
{
static void Main(string[] args)
{
FeatureClass feature = new FeatureClass();
feature.GenerateKey(); //I would like this to produce "Parent_Feature"
SubFeatureClass subFeature = new SubFeatureClass();
subFeature.GenerateKey(); //I would like this to generate "Parent_Feature_SubFeature"
ReallySubFeatureClass reallySubFeature = new ReallySubFeatureClass();
reallySubFeature.GenerateKey();
Console.ReadKey();
}
}
Result:

Related

Downcasting a List<AbstractClass> object to what the object actually is

I have a ParentClass. Two classes are inherit from it, FirstChildClass and SecondChildClass. A class MultipleValueTypes contains a Dictionary and a method that adds values to it. My intention is to be able to pass values of different classes, which inherit from the same abstract class to the value parameter of the Dictionary. Therefore, I initialize the dictionary with the value List<ParentClass> so that I would be able to add objects made with the child classes to the Dictionary. I can do this, but I cannot access them, therefore in the abstract class I create a way to tell them apart, a virtual method that both the children classes override to return their own class type.
I test the values they return against the enum itself and based on whether the condition is fulfilled, the object would be casted as what it is instead of a List<ParentClass>. Is this the wrong approach? Is this impossible?
I think it should work, because in my thinking the FirstObject and SecondObject are still objects of their respective classes, so casting should work and I should be able to access the overridden method.
What doesn't work: I cannot access the method that returns what type of class it is, because it only gets methods from the List<ParentClass>.
What I've tried so far: searching for a way to access the method, but I did not find any.
What I still need help with: everything mentioned above.
public abstract class ParentClass
{
public string Name { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
}
public class FirstChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public FirstChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the FirstChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public SecondChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the SecondChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public Dictionary<string, List<ParentClass>> ADictionary = new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if (!ADictionary.ContainsKey(Name))
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
class Program
{
static void Main(string[] args)
{
FirstChildClass FirstObject = new FirstChildClass("FirstObject");
SecondChildClass SecondObject = new SecondChildClass("SecondObject");
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if(TestDictionary.ADictionary["FirstObject"].TypeOfClass() == ParentClass.ChildClasses.FirstChildClass) ///List<ParentClass>' does not contain a definition for 'TypeOfClass' and no accessible extension method 'TypeOfClass' accepting a first argument of type 'List<ParentClass>' could be found (are you missing a using directive or an assembly reference?)
{
TestDictionary.ADictionary["FirstObject"] = (FirstChildClass)TestDictionary.ADictionary["FirstObject"]; ///Cannot convert type 'System.Collections.Generic.List<Dictionary.ParentClass>' to 'Dictionary.FirstChildClass
}
}
}
You forgot to use indexer of the list value of the key of the dictionary here:
==> TestDictionary.ADictionary["FirstObject"][0]
Here is your code now refactored too:
class Program
{
static void Main(string[] args)
{
var FirstObject = new FirstChildClass("FirstObject");
var SecondObject = new SecondChildClass("SecondObject");
FirstObject.ReturnMessage();
SecondObject.ReturnMessage();
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if ( TestDictionary.ADictionary["FirstObject"][0].TypeOfClass()
== ParentClass.ChildClasses.FirstChildClass )
{
TestDictionary.ADictionary["FirstObject"][0]
= (FirstChildClass)TestDictionary.ADictionary["FirstObject"][0];
}
Console.ReadKey();
}
}
public abstract class ParentClass
{
public string Name { get; set; }
public string RandomValue { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public virtual void ReturnMessage()
{
Console.WriteLine($"This is the {this.GetType().Name} instance");
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
}
public class FirstChildClass : ParentClass
{
public FirstChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
public SecondChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public readonly Dictionary<string, List<ParentClass>> ADictionary
= new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if ( !ADictionary.ContainsKey(Name) )
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
If the intention is to cast the whole list from List<ParentClass> to List<FirstChildClass> and List<SecondChildClass>, then Linq is your friend, just use the Cast function:
List<FirstChildClass> firstChildClasses = TestDictionary.ADictionary["FirstObject"]
.Cast<FirstChildClass>().ToList();
List<SecondChildClass> secondChildClasses = TestDictionary.ADictionary["SecondObject"]
.Cast<SecondChildClass>().ToList();

C# instantiate class with varying "child" class

I have a class that has some derived classes. That works.
I want to instantiate the "parent" class. Got that far...
But I want to instantiate it with one of the "child" classes, and then possibly change that "child" class later. Maybe the deriving is inappropriate here.
Take the following example:
public class Unicorn {
public string Horn { get; set; }
public Unicorn(){
}
}
public class BadUnicorn : Unicorn{
public string Rainbow()
{
return "dark rainbow";
}
}
public class GoodUnicorn : Unicorn{
public string Rainbow()
{
return "light rainbow";
}
}
I could instantiate one of the children, but then if I change one from "good" to "bad", I would have to re-instantiate. And maybe that's just the way it is, and that would be an acceptable answer if that's all there is to it.
I rather want to instantiate a Unicorn, and then be able to change it from Good to Bad to maintain information stored on that Unicorn, but have access to the current methods and properties of the "child" class.
That way when I call Unicorn.Rainbow() it calls the desired method of the "child" class.
I'm a little new to C#, is there a pattern that fits this bill?
You can't do what you want with polymorphism. You cannot change an instance of class from one to another. Once it is created it is always the same type.
You can use composition though.
Here's what you'd need to do:
public class Unicorn
{
public string Horn { get; set; }
public Unicorn(Rainbow rainbow)
{
_rainbow = rainbow;
}
public void SetRainbow(Rainbow rainbow)
{
_rainbow = rainbow;
}
private Rainbow _rainbow;
public string Rainbow()
{
return _rainbow.Colour();
}
}
public abstract class Rainbow
{
public abstract string Colour();
}
public class BadRainbow : Rainbow
{
public override string Colour()
{
return "dark rainbow";
}
}
public class GoodRainbow : Rainbow
{
public override string Colour()
{
return "light rainbow";
}
}
You can test like this:
var unicorn = new Unicorn(new GoodRainbow());
Console.WriteLine(unicorn.Rainbow());
unicorn.SetRainbow(new BadRainbow());
Console.WriteLine(unicorn.Rainbow());
This outputs:
light rainbow
dark rainbow
The instance of Unicorn stays the same, but you can change the rainbow.
Here's my take on delegate dictionary. While it seems superfluous to use Func instead of just string, if the method have additional functionality like calculation or need parameters, you're covered with Func.
public class Unicorn
{
static Dictionary<Attitude, Func<string>> RainbowByAttitude =
new Dictionary<Attitude, Func<string>>()
{
[Attitude.Bad] = new Func<string>(() => "dark rainbow"),
[Attitude.Good] = new Func<string>(()=>"light rainbow")
};
public string Horn { get; set; }
public enum Attitude
{
Good,Bad
}
public Attitude attitude;
public Unicorn(Attitude attitude)
{
this.attitude = attitude;
}
public string Rainbow() => RainbowByAttitude[attitude].Invoke();
}
class Program
{
static void Main(string[] args)
{
Unicorn unicorn;
unicorn = new Unicorn(Unicorn.Attitude.Bad);
Console.WriteLine(unicorn.Rainbow());
unicorn.attitude = Unicorn.Attitude.Good;
Console.WriteLine(unicorn.Rainbow());
}
}
It seems like a state pattern to me like this:
public abstract class UnicornState
{
public abstract UnicornState Change();
public abstract string Rainbow();
}
public sealed class GoodUnicornState : UnicornState
{
public override UnicornState Change()
{
return new BadUnicornState();
}
public override string Rainbow()
{
return "light rainbow";
}
}
public sealed class BadUnicornState : UnicornState
{
public override UnicornState Change()
{
return new GoodUnicornState();
}
public override string Rainbow()
{
return "dark rainbow";
}
}
public class Unicorn
{
public string Horn { get; set; }
public UnicornState State { get; set; }
public string Rainbow => State.Rainbow();
}
Usage:
var u = new Unicorn();
u.State = new GoodUnicornState();
Console.WriteLine(u.Rainbow);
u.State = u.State.Change();
Console.WriteLine(u.Rainbow);

Static method call in generic manner

I have multiple classes like:
public class Base { }
public class Base1: Base { public static List<Base1> LoadFromXml(string path) }
public class Base2: Base { public static List<Base2> LoadFromXml(string path) }
Then I want to have a method like this:
public List<T> PrepareBase<T>() where T: Base { return T.Load("C:\test.xml"); }
So that I don't have to make a method for every type.
But I don't know how to accomplish this or something similar.
The problem is that I can't make the LoadFromXml method known to the base class because static inheritance is not a thing. Neither is creating a seperate interface with a static method.
Is there a way to do this or am I expecting too much?
Edit:
An example of the LoadFromXml method:
public class Base1
{
public int ID { get; set; }
public string PropertyOnlyInBase1 { get; set; }
public static List<Base1> LoadFromXml(string path)
{
List<Base1> baseList = new List<Base1>();
XDocument doc = XDocument.Load(path);
foreach(var node in doc.Descendants("Base1"))
{
Base 1 base = new Base1() { ID = node.Attributes["id"] };
base.PropertyOnlyInBase1 = node.Element("PropertyOnlyInBase1");
baseList.Add(base);
}
return baseList;
}
}
So the Base classes also have some unique properties. That's why I needed the inheritance thing in the first place.
One option is to add a GenericBase:
public abstract class Base
{
}
public static class GenericBase<T>
where T : Base
{
public static List<T> LoadFromXml(string path)
{
//Load from XML
}
}
public class Base1 : Base { }
public class Base2 : Base { }
public class Test //MainForm.cs class or whatever you want
{
public void Tester() //Load event handler or whatever you want
{
List<Base1> base1List = PrepareBase<Base1>();
}
public List<T> PrepareBase<T>() where T : Base
{ return GenericBase<T>.LoadFromXml("C:\test.xml"); }
}
Edit:
As D Stanley mentioned, it's not possible; but I made some work-around that could be helpful for you:
public abstract class Base
{
public static List<T> LoadFromXml<T>(string path) where T : Base, new()
{
List<T> baseList = new List<T>();
XDocument doc = XDocument.Load(path);
foreach (var node in doc.Descendants(typeof(T).Name))
{
T t = new T();
Dictionary<string, string> d = new Dictionary<string, string>();
foreach (var item in node.Elements())
d.Add(item.Name.ToString(), item.Value);
t.Load(d);
baseList.Add(t);
}
return baseList;
}
protected internal abstract void Load(Dictionary<string, string> elements);
}
public class Base1 : Base
{
public string CustomProp1 { get; set; }
public string CustomProp2 { get; set; }
public string CustomProp3 { get; set; }
protected internal override void Load(Dictionary<string, string> elements)
{
if (elements.ContainsKey("CustomProp1"))
CustomProp1 = elements["CustomProp1"];
if (elements.ContainsKey("CustomProp2"))
CustomProp2 = elements["CustomProp2"];
if (elements.ContainsKey("CustomProp3"))
CustomProp3 = elements["CustomProp3"];
}
}
public class Base2 : Base
{
public string CustomProp1 { get; set; }
public string CustomProp2 { get; set; }
public string CustomProp3 { get; set; }
protected internal override void Load(Dictionary<string, string> elements)
{
if (elements.ContainsKey("CustomProp1"))
CustomProp1 = elements["CustomProp1"];
if (elements.ContainsKey("CustomProp2"))
CustomProp2 = elements["CustomProp2"];
if (elements.ContainsKey("CustomProp3"))
CustomProp3 = elements["CustomProp3"];
}
}
public class Test //MainForm.cs class or whatever you want
{
public void Tester() //Load event handler or whatever you want
{
List<Base1> base1List = PrepareBase<Base1>();
}
public List<T> PrepareBase<T>() where T : Base, new()
{
return Base.LoadFromXml<T>("C:\test.xml");
}
}
I think you're correct that the class that loads these from XML should be separate from the class that's being loaded. As you said, it has no real connection to the instance.
Perhaps what you need is a separate class that loads those instances for you.
public class BaseXmlLoader<TBase> where TBase : Base
{
public List<TBase> LoadFromXml(string filePath)
{
var serializer = new XmlSerializer(typeof(TBase));
// Load your file and deserialize.
}
}
The benefits aren't huge because it's not saving you that much code. But if the LoadFromXml methods are essentially the same except for the type then you're getting something out of it.
I changed my approach to the problem and solved it using the Factory pattern. I also provided each class with an instance method SetPropertiesFromXml to handle the custom properties. Unlike the previously used method, a method like that made sense as an instance method.
Factory:
public static class BaseFactory
{
public static Base GetBase(string id)
{
switch(id) { case '1': return new Base1(); ... }
}
public static T GetBaseList<T>(string xml, string tagName) where T: Base
{
List<T> list = new List<T>();
var nodes = XDocument.Load(xml).Descendants(tagName);
foreach(XElement node in nodes)
{
var base = GetBase(node.Attribute("id").Value);
base.SetPropertiesFromXml(node);
list.Add(base as T);
}
}
}
Bases
public abstract class Base
{
public virtual void SetPropertiesFromXml(XElement node)
{
//<Set Properties like: this.Property = node.Element("key");>
}
}
public class Base1
{
public override void SetPropertiesFromXml(XElement node)
{
//<Set Custom Properties for Base1>
//Call Base to add the normal properties as well
base.SetPropertiesFromXml(node);
}
}
Call
List<Base1> list = BaseFactory.GetBaseList<Base1>("test.xml", "Base1");

Access const with generics C#

I have the following base class:
public class Base
{
public string LogicalName { get; set; }
public int NumberOfChars { get; set; }
public Base()
{
}
public Base(string logicalName, int numberOfChars)
{
LogicalName = logicalName;
NumberOfChars = numberOfChars;
}
}
and the following derived classes:
public class Derived1 : Base
{
public const string EntityLogicalName = "Name1";
public const int EntityNumberOfChars = 30;
public Derived1() : base(EntityLogicalName, EntityNumberOfChars)
{
}
}
public class Derived2 : Base
{
public const string EntityLogicalName = "Name2";
public const int EntityNumberOfChars = 50;
public Derived2()
: base(EntityLogicalName, EntityNumberOfChars)
{
}
}
and I also have this function that is provided by a service:
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
//Some code to get the entities
}
My problem is how can I call this function generically? I want to call it with something that looks like this:
public void TestEntities<T>() where T : Base
{
var entities = GetEntities<T>(T.EntityLogicalName, T.EntityNumberOfChars);
//some other code to test the entities
}
This of course doesn't work because at this point T is not known. How can I accomplish something similar to this? EntityLogicalName and EntityNumberOfChars are characteristics that all Base derived classes have and they never change for each derived class. Can I get them from the Base class without instantiating objects or some other way that I am not seeing?
Replace constants with getter abstract properties
public abstract class Base
{
public abstract string LogicalName { get; }
public abstract int NumberOfChars { get; }
public Base()
{
}
}
public class Derived1 : Base
{
public string LogicalName { get { return "Name1"; } }
public int NumberOfChars { get { return 30; } }
public Derived1() : base()
{
}
}
Also, you will be able to put some logic into overriden getter, e.g. :
...
public string LogicalName { get { return this.EntityMap.Name; } }
...
UPDATE: The fact that you do not want to instantiate object from class but want to be able to get that string in a strongly typed manner can be handled in one more way. It is totally separate from answer above ( Since you can't override static props in c#). Consider the following code. We are adding one more class here, but LocatorInner can be a member of BaseClass. We are using this approach a lot in several existing apps.:
public class Locator
{
public static class LocatorInner<T> where T : BaseClass
{
public static string Name { get; set; }
}
public static string GetName<T>() where T : BaseClass
{
return LocatorInner<T>.Name;
}
public static void SetName<T>(string name) where T : BaseClass
{
LocatorInner<T>.Name = name;
}
}
public class BaseClass
{
}
public class DerivedClass: BaseClass
{
static DerivedClass()
{
Locator.LocatorInner<DerivedClass>.Name = "me";
}
}
public class TestClass<T> where T : BaseClass
{
public void Method()
{
var name = Locator.GetName<T>();
}
}
IMHO, I believe using constants here is a bad design decision.
You can either solve the issue using #vittore approach, but for me it sounds like you should use meta-programming with attributes if you're looking to get data from the T generic argument
For example, what about:
public class LogicalNameAttribute : Attribute
{
public LogicalNameAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class NumberOfCharsAttribute : Attribute
{
public NumberOfCharsAttribute (int number)
{
Number = number;
}
public string Number { get; private set; }
}
[LogicalName("Name1"), NumberOfChars(30)]
public class Derived1 : Base
{
public Derived1() : base()
{
}
}
Now your service method can extract attribute metadata as follows:
public void TestEntities<T>() where T : Base
{
LogicalNameAttribute logicalNameAttr = typeof(T).GetCustomAttribute<LogicalNameAttribute>();
NumberOfCharsAttribute numberOfCharsAttr = typeof(T).GetCustomAttribute<NumberOfCharsAttribute >();
Contract.Assert(logicalNameAttr != null);
Contract.Assert(numberOfCharsAttr != null);
string logicalName = logicalNameAttr.Name;
int numberOfChars = numberOfCharsAttr.Number;
// Other stuff
}
There's a performance penalty because you need to use reflection to get attributes applied to T, but you gain the flexibility of not forcing derived classes to provide this static info.
As #vittore mentioned, move the properties to base,pass the hard coded values from derived and in creation use just defautl(T)
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
yield return default(T); //Is its always class use new constraint and return new T();
}

Override only Get accessor

I got an abstract class :
abstract class ClassBase
{
public abstract string Test { get; }
}
I want to derive it and by the way add a set accesor
class ClassDerive : ClassBase
{
string _s;
public override string Test
{
get { return _s; }
set { _s = value; }
}
}
I can't do that because i may not override set
class ClassDerive2 : ClassBase
{
string _s;
public string Test
{
override get { return _s; }
set { _s = value; }
}
}
Syntax error
class ClassDerive3 : ClassBase
{
string _s;
public override string ClassBase.Test
{
get { return _s; }
}
public string Test
{
set { _s = value; }
}
}
Syntax error
Any Idea ???
thx
You cannot do exactly what you want to do but here is a workaround:
abstract class ClassBase
{
public abstract String Test { get; }
}
class ClassDerive : ClassBase
{
string _s;
public override string Test
{
get { return _s; }
}
public void SetTest(String test)
{
this._s = test;
}
}
This will make Test only settable in ClassDerived via the public SetTest method. I know this is not as clean as using the property's setter but it is about as good as it's going to get.
If at first you have defined a read-only property in a type, you can't later change it to a read/write property in a derived class. That's simply how .NET works, and can't be changed.
If, on the other hand, you define an interface with a read-only property, you can later implement that interface in a class with a writable property.
If you'd like to share what you are trying to achieve, perhaps we can come up with a design that works and can compile :)
Another way:
abstract class ClassBase
{
public abstract string Test { get; }
}
class ClassDerive : ClassBase
{
string _s;
protected void setTest(string s)
{
_s = s;
}
public override string Test
{
get { return _s; }
}
}
class ClassDerive2 : ClassDerive
{
public new string Test
{
get { return base.Test; }
set { setTest(value); }
}
}
class Program
{
static void Main(string[] args)
{
var cd2 = new ClassDerive2();
cd2.Test = "asdf";
Console.WriteLine(cd2.Test);
}
}
My first thought was also to implement it as an interface. If this fits in with your design, the following code will work:
public interface TestInterface
{
string TestProperty { get; }
}
public class TestClass : TestInterface
{
public string TestProperty
{
get { return "test"; }
set { string t = value; }
}
}
No you cant, sorry. It is by design, so it's the law.

Categories