In C#, what is the best way to access a property of the derived class when the generic list contains just the base class.
public class ClassA : BaseClass
{
public object PropertyA { get; set; }
}
public class ClassB: BaseClass
{
public object PropertyB { get; set; }
}
public class BaseClass
{
}
public void Main
{
List<BaseClass> MyList = new List<BaseClass>();
ClassA a = new ClassA();
ClassB b = new ClassB();
MyList.Add(a);
MyList.Add(b);
for(int i = 0; i < MyList.Count; i++)
{
//I would like to access PropertyA abd PropertyB from the derived classes
}
}
Certainly you can downcast, like so:
for (int i = 0; i < MyList.Count; i++)
{
if (MyList[i] is ClassA)
{
var a = ((ClassA)MyList[i]).PropertyA;
// do stuff with a
}
if (MyList[i] is ClassB)
{
var b = ((ClassB)MyList[i]).PropertyB;
// do stuff with b
}
}
... However, you should take another look at what you're trying to accomplish. If you have common code that needs to get to properties of ClassA and ClassB, then you may be better off wrapping access to those properties up into a shared, virtual property or method in the ancestor class.
Something like:
public class BaseClass
{
public virtual void DoStuff() { }
}
public class ClassA : BaseClass
{
public object PropertyA { get; set; }
public override void DoStuff()
{
// do stuff with PropertyA
}
}
public class ClassB : BaseClass
{
public object PropertyB { get; set; }
public override void DoStuff()
{
// do stuff with PropertyB
}
}
Further to TimJ's answer, you can write one extension method that will work for all types:
public static IEnumerable<T> OfType<T>(this IEnumerable list)
{
foreach (var obj in list)
{
if (obj is T)
yield return (T)obj;
}
}
Or if you have Linq, that function is in the namespace System.Linq.
BaseClass o = MyList[i];
if (o is ClassB)
{
object k = ((ClassB)o).PropertyB;
}
if (o is ClassA))
{
object j = ((ClassA)o).PropertyA;
}
If you are doing this a lot, another option would be to create an extension method on the list to give you back the correctly typed enumeration. i.e.
public static class MyBaseListExtensions
{
public static IEnumerable<ClassA> GetAllAs(this List<MyBaseClass> list)
{
foreach (var obj in list)
{
if (obj is ClassA)
{
yield return (ClassA)obj;
}
}
}
public static IEnumerable<ClassB> GetAllbs(this List<MyBaseClass> list)
{
foreach (var obj in list)
{
if (obj is ClassB)
{
yield return (ClassB)obj;
}
}
}
}
Then you could use it like....
private void button1_Click(object sender, EventArgs e)
{
ClassA a1 = new ClassA() { PropertyA = "Tim" };
ClassA a2 = new ClassA() { PropertyA = "Pip" };
ClassB b1 = new ClassB() { PropertyB = "Alex" };
ClassB b2 = new ClassB() { PropertyB = "Rachel" };
List<MyBaseClass> list = new List<MyBaseClass>();
list.Add(a1);
list.Add(a2);
list.Add(b1);
list.Add(b2);
foreach (var a in list.GetAllAs())
{
listBox1.Items.Add(a.PropertyA);
}
foreach (var b in list.GetAllbs())
{
listBox2.Items.Add(b.PropertyB);
}
}
The whole premise doesn't make sense - what would PropertyB be for the a instance?
You can do this if you do manual runtime type checking (inst is Foo), and then cast to the type with the property you want.
You might have some issues with Generics and subclasses (in which case you should go back to System.Collections.ArrayList), but you have to cast the BaseClass to the subclass you wish to use. If you use the 'as' directory, it will succeed if the BaseClass can be casted to the subclass, or it will be null if it cannot be cast. It would look something like:
for(int i = 0; i < MyList.Count; i++)
{
BaseClass bc = MyList[i];
ClassA a = bc as ClassA;
ClassB b = bc as ClassB;
bc.BaseClassMethod();
if (a != null) {
a.PropertyA;
}
if (b != null) {
b.PropertyB;
}
}
Also, I should mention that this smells a bit bad. This is the kind of code that indicates a poorly structured object heirarchy. In general, if you can't say a IS A BaseClass, your design is probably wrong. But, hope that helps!
You would need to have the properties be declared as virtual on the base class and then override them in the derived class.
Ex:
public class ClassA : BaseClass
{
public override object PropertyA { get; set; }
}
public class ClassB: BaseClass
{
public override object PropertyB { get; set; }
}
public class BaseClass
{
public virtual object PropertyA { get; set; }
public virtual object PropertyB { get; set; }
}
public void Main
{
List<BaseClass> MyList = new List<BaseClass>();
ClassA a = new ClassA();
ClassB b = new ClassB();
MyList.Add(a);
MyList.Add(b);
for(int i = 0; i < MyList.Count; i++)
{
// Do something here with the Property
MyList[i].PropertyA;
MyList[i].PropertyB;
}
}
You would either need to implement the property in the base class to return a default value (such as null) or to make it abstract and force all the derived classes to implement both properties.
You should also note that you could return different things for say PropertyA by overrideing it in both derived classes and returning different values.
Related
I have a question about overriding properties in C#. There already is a similar question here, but the answers are not satisfying for me. Let's say I have these classes:
class A
{
public int Prop { get; }
}
class B : A
{
public int Prop { get; set; }
}
Now as you can see I want to add a setter to the property Prop in a subclass. I came up with two solutions. The first one is making the property virtual and overriding it in class B like this:
class A
{
public virtual int Prop { get; }
}
class B : A
{
public override int Prop { get; set; }
}
But unfortunately the compiler doesn't allow me to do this. My second idea was to use a 'new' keyword:
class A
{
public virtual int Prop { get; }
}
class B : A
{
public new int Prop { get; set; }
}
Now everything seemingly works, but it's not a satisfying solution for me because of one detail. Let's consider for instance this piece of code:
B b = new B();
b.Prop = 5;
A a = b;
Console.WriteLine(a.Prop);
You probably know that I get 0 here in my output, but I want to get 5. Is there any way to solve this problem?
You could try to explicitly implement property's setter. This requires an interface:
public interface IPropSet
{
int Prop { set; }
}
class A
{
protected int prop;
public int Prop => prop;
}
class B : A, IPropSet
{
int IPropSet.Prop
{
set => prop = value;
}
}
But unfortunately this property cannot be set without casting to IPropSet:
((IPropSet)new B()).Prop = 1;
Another option is to use a backing field and to create the Prop as new in B as follows:
class A
{
protected int prop;
public int Prop => prop;
}
class B : A
{
public new int Prop
{
get => prop;
set => prop = value;
}
}
Sample usage:
var b = new B { Prop = 1 };
Console.WriteLine(((A)b).Prop); // 1
On Console.WriteLine(a.Prop); you reference to A.Prop, new in B class for Prop is for redefining.
When used as a declaration modifier, the new keyword explicitly hides a member that is inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base class version. This assumes that the base class version of the member is visible, as it would already be hidden if it were marked as private or, in some cases, internal. Although you can hide public or protected members without using the new modifier, you get a compiler warning. If you use new to explicitly hide a member, it suppresses this warning. Microsoft docs
but you can use,
if (a is B bb)
{
Console.WriteLine(bb.Prop);
}
Or use this pattern
class A
{
public virtual int Prop { get; protected set; }
}
class B : A
{
public void SetProp(int prop) => Prop = prop;
}
B b = new B();
b.SetProp(5);
A a = b;
Console.WriteLine(a.Prop);
Property's set-ter in class A should be protected. You will still be able to override it and it still won't be accessible outside class A and its children.
Edit: I've read your question once again and tested my edited answer in Visual Studio (I haven't had a chance to do it the first time).
As I understand, besides overriding the property, you want to be able to set property's value on a subclass, from outside the class, but not setting it on the base class.
You could try something like this:
using System;
namespace PropertyInheritance
{
public class Program
{
static void Main(string[] args)
{
A a1 = new A();
B b1 = new B();
a1.Prop = 1;
b1.Prop = 2;
Console.WriteLine($"a1.Prop = {a1.Prop}");
Console.WriteLine($"b1.Prop = {b1.Prop}");
Console.WriteLine($"a1.GetPropField() = {a1.GetPropField()}");
Console.WriteLine($"b1.GetPropField() = {b1.GetPropField()}");
B b2 = new B();
b2.Prop = 5;
A a2 = b2;
Console.WriteLine($"a2.Prop = {a2.Prop}");
Console.WriteLine($"a2.GetPropField() = {a2.GetPropField()}");
Console.ReadLine();
}
}
public class A
{
protected int prop;
public virtual int Prop {
get { return prop; }
set { }
}
// test method - to check field's value
public int GetPropField() => prop;
}
public class B : A
{
public override int Prop
{
get { return prop; }
set { prop = value; }
}
}
}
Here is the output:
I suppose everything is clear, but if not, please feel free to ask. Maybe I still didn't understand the question, or even made some mistake in my answer.
A is not a subclass of B, this is not how inheritance works. I don't understand why do you want to do this, I think you are mistaken the complete concept of inheritance
In the case you proposes:
class A
{
public int Prop { get; }
}
class B : A
{
public int Prop { get; set; }
}
they are the same property. If you do a:
class A
{
public int Prop { get; }
}
class B : A
{
public int AnotherProp { get; set; }
}
you can set:
B instance = new B();
B.Prop = 5;
If what you want to do is having a property in a subclass with the same name (not recommended) you can do this, without working with inheritance:
internal class A
{
internal int Prop { get; }
}
internal class B
{
internal A MySubClass { get; set; }
}
B instanceB = new B();
A instanceA = new A();
instanceA.Prop = 5;
B.MySubClass = instanceA;
or you can play with that, without copy it directly. Is just an example to show you the difference between class as property and inheritance
public BaseClass
{
prop abc;
prop pqr;
prop xyz;
}
public DerivedClass : BaseClass
{
prop New1;
prop New2;
//constructor
public DerivedClass(BaseClass baseObj,someMore params)
{
this.abc = baseObj.abc;
this.pqr = baseObj.pqr;
this.xyz = baseObj.xyz;
/* I do not want to do this for each and every property as I have more than 40 properties */
}
}
Here in above code How I can set all properties of derived class which are same in derived class as base class.
In my derived class
Can I do somethign of following type to achieve above thing without using Automapper or Reflection
public DerivedClass(BaseClass baseObj,someMore params):base(baseObj) //or something similar
{
}
You could initialize the properties in your base class instead of the derived class (since both the parameter and the base classes share the same type of class).
To copy the properties, besides AutoMapper (which I find really slow) and reflection (which is hard to implement and maintain), an easy, very efficient way to do this is using the open source library Omu.ValueInjecter:
Install the library from NuGet:
Install-Package ValueInjecter -Version 3.1.3
Then, use it in your constructor as follows:
using Omu.ValueInjecter;
public abstract class BaseClass
{
protected BaseClass(BaseClass baseObj)
{
this.InjectFrom(baseObj);
}
public string Abc { get; set; }
public int Pqr { get; set; }
public object Xyz { get; set; }
}
public class DerivedClass : BaseClass
{
public DerivedClass(BaseClass baseObj, int new1, object new2) : base(baseObj)
{
New1 = new1;
New2 = new2;
}
public int New1 { get; set; }
public object New2 { get; set; }
}
The first time you run this code, it will create a mapper and store it in memory so the following times you perform the same operation will be much faster.
If you don't want to use value injecter or any other library, simply set the properties manually in your base class.
public abstract class BaseClass
{
protected BaseClass(BaseClass baseObj)
{
Abc = baseObj.Abc;
Pqr = baseObj.Pqr;
Xyz = baseObj.Xyz;
}
[...]
}
You can use prototype pattern. If you use C#, Please refer code as below:
public abstract class BaseClass
{
public int a;
public int b;
public int c;
public abstract BaseClass Clone();
}
public class DerivedClass : BaseClass
{
public int new1;
public int new2;
public override BaseClass Clone()
{
return this.MemberwiseClone() as BaseClass;
}
public override string ToString()
{
return string.Format("{0}{1}{2}{3}{4}", a, b, c, new1, new2);
}
}
class Program
{
static void Main(string[] args)
{
DerivedClass AClass = new DerivedClass();
AClass.a = 1;
AClass.b = 2;
AClass.c = 3;
DerivedClass BClass = AClass.Clone() as DerivedClass;
BClass.new1 = 4;
BClass.new2 = 5;
Console.WriteLine(BClass.ToString());
}
}
It comes from https://mobilechos.blogspot.com/2019/04/prototype-pattern-with-csharp.html.
Let's say I have a the classes A, B, C and D with B:A and D:C.
A has a field with a C object that gets inherited to B and is used in different methods in A. I know want to specify that in B, it is not only a C object, but a D object, but still utilize the methods in A that operate on the C object.
public class A
{
public C Obj { get; set; }
public void DoStuff()
{
// Do stuff with Obj (C)
}
}
public class B : A
{
public D Obj { get; set; } // This should also be the C Obj in A
public void DoMoreStuff()
{
// Do stuff with Obj (D)
}
}
public class C
{
// ...
}
public class D : C
{
// ...
}
Specifically I need this to implement Binary Trees. A Binary-Search-Tree (BST) has a root that is a BST-Node and provides different methods that utilize it. A Red-Black-Tree is also a BST but the root is a RBT-Node, that is also a BST-Node, but additionally has a color attribute.
You can do what you want with a generic base class. Try starting with this:
public abstract class A<T> where T : C
{
public T Obj { get; set; }
public void DoStuff()
{
Console.WriteLine(typeof(T).FullName);
Console.WriteLine(this.Obj.GetType().FullName);
}
}
Now you can define A and B easily:
public class A : A<C>
{
}
public class B : A<D>
{
public void DoMoreStuff()
{
this.DoStuff();
Console.WriteLine(this.Obj.GetType().FullName);
}
}
If I run this code:
var a = new A() { Obj = new C() };
var b = new B() { Obj = new D() };
a.DoStuff();
Console.WriteLine("...");
b.DoMoreStuff();
I get:
C
C
...
D
D
D
It's quite easy using generics:
public class A<T> where T : C
{
public T Obj { get; set; }
public void DoStuff()
{
// Do stuff with Obj (C)
}
}
public class B<T> : A<T> where T : D // this condition is valid since D inherits C
{
public T Obj { get; set; }
public void DoMoreStuff()
{
// Do stuff with Obj (D)
}
}
public class C
{
// ...
}
public class D : C
{
// ...
}
You can add in some generics to gain access to the properties you want. I feel like this is a homework exercise, so I'll just give you the basics. See comments in the code for more details
public abstract class BaseTree<TNode>
where TNode : BaseNode // TNode must be at least (base class) a BaseNode
{
// Can be a collection as well, depending on your needs
public TNode Node { get; set; }
public void DoStuff()
{
// Node is a BaseNode
}
}
// Any node in this tree is a RedBlackNode
public class RedBlackTree : BaseTree<RedBlackNode>
{
public void DoMoreStuff()
{
// Node is a RedBlackNode
}
}
public abstract class BaseNode
{
}
public class RedBlackNode : BaseNode
{
}
I am trying to figure out how to simplify the following
let's say I have 2 entity classes
public class A
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
}
AND
public class B
{
public int Id { get; set; }
public string Nom { get; set; }
public string Ville { get; set; }
}
classes that are similar, but not the same.
each class has a repository classes it uses for CRUD Operations, for example...
public class RepA
{
public static List<A> GetAll()
{
List<A> list = new List<A>();
A a1 = new A() {Id=1, Name="First A", City="Boston"};
A a2 = new A() {Id=2, Name="First B", City="Chicago"};
A a3 = new A() {Id=3, Name="First C", City="San Francisco"};
list.Add(a1);
list.Add(a2);
list.Add(a3);
return list;
}
public static void SaveAll(List<A> list)
{
foreach (A a in list)
{
Console.WriteLine("Saved Id = {0} Name = {1} City={2}",
a.Id, a.Name, a.City);
}
}
}
AND
public class RepB
{
public static List<B> GetAll()
{
List<B> list = new List<B>();
B b1 = new B() {Id=1, Nom="Second A", Ville="Montreal"};
B b2 = new B() {Id=2, Nom="Second B", Ville="Paris"};
B b3 = new B() {Id=3, Nom="Second C", Ville="New Orleans"};
list.Add(b1);
list.Add(b2);
list.Add(b3);
return list;
}
public static void SaveAll(List<B> list)
{
foreach (B b in list)
{
Console.WriteLine("Saved Id = {0} Name = {1} City={2}", b.Id,
b.Nom, b.Ville);
}
}
}
How would I go about making anonymous call to my repository without having to resort to this, because in my real world example, i have 100 repositories, and not 2.
void Main()
{
ChosenType chosentype = RandomChosenType(); //A or B
switch (chosentype)
{
case ChosenType.A:
var listA = RepA.GetAll();
RepA.SaveAll(listA);
break;
case ChosenType.B:
var listB = RepB.GetAll();
RepB.SaveAll(listB);
break;
default:
break;
}
}
Make a base class or use an interface:
public interface IBase<T>
{
List<T> GetAll();
void SaveAll(List<T> items);
}
public class RepA : IBase<RepA>
{
public List<RepA> GetAll() { return new List<RepA>(); }
public void SaveAll(List<RepA> repA) { }
}
public class RepB : IBase<RepB>
{
public List<RepB> GetAll() { return new List<RepB>(); }
public void SaveAll(List<RepB> repB) { }
}
void Main()
{
IBase chosenType = RandomChosenType();
var list = chosenType.GetAll();
}
You should use a single generic repository. The operations should be handled by injected delegates. A repository could look like this:
public class GenericRepositoryExample
{
public void Save<T>(IList<T> persons, SaveDelegate<T> save)
{
foreach (T person in persons)
{
Console.WriteLine(save(person));
}
}
}
Note that the save delegate is passed to the Save method. The SaveDelegate in your example could be declared as:
public delegate string SaveDelegate<T>(T input);
For ease, I have created a HelperClass containing the delegated functions. In real life helper classes should generally be avoided if possible.
public static class HelperClass
{
public static string FrenchSave(B frenchInput)
{
string result = string.Format("ID = {0}; Name = {1}; City = {2}", frenchInput.Id, frenchInput.Nom, frenchInput.ville);
return result;
}
public static string EnglishSave(A englishInput)
{
string result = string.Format("ID = {0}; Name = {1}; City = {2}", englishInput.Id, englishInput.name, englishInput.city);
return result;
}
}
To illustrate the use of this setup, I have created the following unit test:
[Test]
public void TestGenericRepository()
{
IList<A> aList = new List<A>();
aList.Add(new A() { Id = 1, name = "George", city = "Chicago"});
aList.Add(new A() { Id = 2, name = "Bill", city = "Toledo" });
List<B> bList = new List<B>();
bList.Add(new B() {Id= 1, Nom = "Nathalie", ville = "Paris"});
bList.Add(new B() {Id = 2, Nom = "Michelle", ville = "Lyon"});
GenericRepositoryExample repository = new GenericRepositoryExample();
repository.Save<A>(aList,HelperClass.EnglishSave);
repository.Save<B>(bList,HelperClass.FrenchSave);
}
You can make your repositories implement an interface, say IGetAllSaveAll. Then you can store your repositories in a list, and cast them to that interface. That way you'll be able to call the GetAll function on all of them:
(actually the first interface isn't mandatory, you could directly write it as IEnumerable<object> GetAll()...)
interface IGetAllSaveAll<T>
{
IEnumerable<T> GetAll();
void SaveAll(IEnumerable<T> obj);
}
you'll need to have a base interface:
interface IGetAllSaveAll : IGetAllSaveAll<object>
and to use it:
public class RepA: IGetAllSaveAll
public class RepB: IGetAllSaveAll
....
Then you can keep a dictionnary of all these repositories somewhere:
Dictionnary<Type, IGetAllSaveAll> myDic;
Of course you'll still have to add your repositories to your dictionnary:
myDic.Add(typeof(A), new RepA());
And then to call it:
Type t = RandomChosenType();
myDic[t].GetAll();
The code you posted uses static methods. In order to implement an interface, you will need instance methods. Unless you want to use reflection (should be avoided in my opinion), these methods need to be ignorant of the type. Something like this:
public interface IRepository {
IEnumerable<object> GetAll();
}
And in RepA:
IEnumerable<object> IRepository.GetAll() {
return RepA.GetAll();
}
Instead of storing types, each of your menu selections can just contain an instance of the appropriate repository class in a field of type IRepository. After calling GetAll on one of the instances, you can later cast the result to the specific type (like List<A>) if necessary.
Try this approach based on reflection and some assumptions about your classes' structures:
static void Main(string[] args)
{
var types = Assembly.GetExecutingAssembly().Modules
.SelectMany(m => m.GetTypes())
.Where(t =>
t.GetMethod("GetAll") != null &&
t.GetMethod("SaveAll") != null &&
t.GetMethod("GetAll").ReturnType.IsGenericType)
.Select(t =>
new
{
RepositoryType = t,
ReturnTypeArgument =
t.GetMethod("GetAll").ReturnType.GenericTypeArguments[0]
}
)
.ToList();
(new List<dynamic> { new A(), new B() }).ToList().ForEach(chosenType =>
{
var association = types
.FirstOrDefault(t =>
t.ReturnTypeArgument == chosenType.GetType());
if (association == null)
return;
var repType = association.RepositoryType;
dynamic list = repType.GetMethod("GetAll")
.Invoke(chosenType, new object[] { });
repType.GetMethod("SaveAll")
.Invoke(chosenType, new object[] { list });
});
}
Given your exact scenario, where you've got an enum representing each of the possible data types, here's something that may work.
Map each enum value to a repository type using an attribute. Each repository inherits from a generic class, which implements a basic interface which is not strongly typed. The repo methods change from static to instance members. The base repo class has to do casting to cast object to the appropriate type and back, but the actual repository implementations are strongly typed.
You can take this a step further and try to cache some of the reflection using expression trees so you only have to do it once, but it depends on how optimized you really need to make it.
public enum ChosenType {
[Repo(typeof(RepA))] A = 0,
[Repo(typeof(RepB))] B = 1
}
public class RepoAttribute : Attribute {
public RepoAttribute(Type repoType) { RepoType = repoType; }
public Type RepoType { get; set; }
}
class Program
{
static void Main()
{
ChosenType chosentype = RandomChosenType(); //A or B
// Make an instance of the appropriate repo based on the mapping
// to the enum value.
// This is a moderately expensive call, and there's room for improvement
// by using expression trees and caching lambda expressions.
var repo = (IRepo)Activator.CreateInstance(
((RepoAttribute)typeof(ChosenType).GetMember(chosentype.ToString())
.Single().GetCustomAttributes(typeof(RepoAttribute), false).Single()
).RepoType);
var list = repo.GetAll();
repo.SaveAll(list);
Console.Read();
}
static Random _rand = new Random();
static ChosenType RandomChosenType()
{
return (ChosenType)_rand.Next(0, 2);
}
}
public class A { /* No change */ }
public class B { /* No change */ }
public interface IRepo {
List<object> GetAll();
void SaveAll(List<object> list);
}
public abstract class Repo<T> : IRepo {
List<object> IRepo.GetAll() {
return GetAll().Cast<object>().ToList();
}
void IRepo.SaveAll(List<object> list) {
SaveAll(list.Cast<T>().ToList());
}
public abstract List<T> GetAll();
public abstract void SaveAll(List<T> list);
}
public class RepA : Repo<A> {
public override List<A> GetAll() { /* No change except the signature */ }
public override void SaveAll(List<A> list) { /* No change except the signature */ }
}
public class RepB : Repo<B> {
public override List<B> GetAll() { /* No change except the signature */ }
public override void SaveAll(List<B> list) { /* No change except the signature */ }
}
I would like to only force the implementation of a C# getter on a given property from a base abstract class. Derived classes might, if they want, also provide a setter for that property for public use of the statically bound type.
Given the following abstract class:
public abstract class Base
{
public abstract int Property { get; }
}
If I want a derived class that also implements a setter, I could naively try:
public class Derived : Base
{
public override int Property
{
get { return field; }
set { field = value; } // Error : Nothing to override.
}
private int field;
}
But then I get a syntax error since I try to override the non existing setter. I tried some other way such as declaring the base setter private and such and I still stumble upon all kind of errors preventing me from doing that. There must be a way to do that as it doesn't break any base class contract.
Incidentaly, it can be done with interfaces, but I really need that default implementation.
I stumbled into that situation so often, I was wondering if there was a hidden C# syntax trick to do that, else I will just live with it and implement a manual SetProperty() method.
You can't do it directly, since you can't new and override with the same signature on the same type; there are two options - if you control the base class, add a second property:
public abstract class Base
{
public int Property { get { return PropertyImpl; } }
protected abstract int PropertyImpl {get;}
}
public class Derived : Base
{
public new int Property {get;set;}
protected override int PropertyImpl
{
get { return Property; }
}
}
Else you can introduce an extra level in the class hierarchy:
public abstract class Base
{
public abstract int Property { get; }
}
public abstract class SecondBase : Base
{
public sealed override int Property
{
get { return PropertyImpl; }
}
protected abstract int PropertyImpl { get; }
}
public class Derived : SecondBase
{
public new int Property { get; set; }
protected override int PropertyImpl
{
get { return Property; }
}
}
Would this suit your needs?
public abstract class TheBase
{
public int Value
{
get;
protected set;
}
}
public class TheDerived : TheBase
{
public new int Value
{
get { return base.Value; }
set { base.Value = value; }
}
}
The virtual was removed, but the base value is still the only storage for the value. So this should show '5'. And the compiler should fuss about b.Value = 4;
TheDerived d = new TheDerived();
d.Value = 5;
TheBase b = d;
//b.Value = 4; // uncomment for compiler error
cout << "b.Value == " << b.Value << endl;
-Jesse
What about something like:
public abstract class Base
{
public virtual int Property
{
get { return this.GetProperty(); }
set { }
}
protected abstract int GetProperty();
}
I had a similar requirement where I needed an interface to be able to share common sorting functionality between two loosely related classes. One of them had a read-only Order property and the other had a read-write Order property, but I needed a way to read the property the same way from both classes.
It turns out that this can be done by hiding the read-only value in a derived interface. Here is how I did it.
interface ISortable
{
int Order { get; }
}
interface ISortableClass2
: ISortable
{
// This hides the read-only member of ISortable but still satisfies the contract
new int Order { get; set; }
}
class SortableClass1
: ISortable
{
private readonly int order;
public SortableClass1(int order)
{
this.order = order;
}
#region ISortable Members
public int Order
{
get { return this.order; }
}
#endregion
}
class SortableClass2
: ISortableClass2
{
#region ISortableClass2 Members
public int Order { get; set; }
#endregion
}
class RunSorting
{
public static void Run()
{
// Test SortableClass1
var list1 = new List<SortableClass1>();
list1.Add(new SortableClass1(6));
list1.Add(new SortableClass1(1));
list1.Add(new SortableClass1(5));
list1.Add(new SortableClass1(2));
list1.Add(new SortableClass1(4));
list1.Add(new SortableClass1(3));
var sorted1 = SortObjects(list1);
foreach (var item in sorted1)
{
Console.WriteLine("SortableClass1 order " + item.Order);
}
// Test SortableClass2
var list2 = new List<SortableClass2>();
list2.Add(new SortableClass2() { Order = 6 });
list2.Add(new SortableClass2() { Order = 2 });
list2.Add(new SortableClass2() { Order = 5 });
list2.Add(new SortableClass2() { Order = 1 });
list2.Add(new SortableClass2() { Order = 4 });
list2.Add(new SortableClass2() { Order = 3 });
var sorted2 = SortObjects(list2);
foreach (var item in sorted2)
{
Console.WriteLine("SortableClass2 order " + item.Order);
}
}
private static IEnumerable<T> SortObjects<T>(IList<T> objectsToSort) where T : ISortable
{
if (objectsToSort.Any(x => x.Order != 0))
{
return objectsToSort.OrderBy(x => x.Order);
}
return objectsToSort;
}
}
You may do this with a constructor as following;
public abstract class Base
{
public abstract int Property { get; }
}
public class Derived : Base
{
public Derived(string Property) : base(Property)
{
}
}