I have something like this:
public class ImplicitClientA : IGenericItems<IGenericItemA>, IGenericItems<IGenericItemB>
public class ImplicitClientB : ImplicitClientA, IGenericItems<IGenericItemC>
and I want to override IGenericItems<IGenericItemA> and IGenericItems<IGenericItemB> in class ImplicitClientB.
Which is the best way?
To create a virtual protected method in ImplicitClientA and
override it in ImplicitClientB. or...
To explicit implement IGenericItems<IGenericItemA> and
IGenericItems<IGenericItemB> in class ImplicitClientB.
Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharpConsoleApplication.Tests
{
public class InterfacesTest
{
public static void Run()
{
var implA = new ImplicitClientA();
IGenericItems<IGenericItemA> implA1 = implA;
IGenericItems<IGenericItemB> implA2 = implA;
Console.WriteLine("Text value for a is: " + implA1.Items.ToList()[0].GetTextValue());
Console.WriteLine("Number value for a is: " + implA2.Items.ToList()[0].GetNumberValue());
Console.WriteLine();
var implB = new ImplicitClientB();
IGenericItems<IGenericItemA> implB1 = implB;
IGenericItems<IGenericItemB> implB2 = implB;
IGenericItems<IGenericItemC> implB3 = implB;
Console.WriteLine("Text value for b is: " + implB1.Items.ToList()[0].GetTextValue());
Console.WriteLine("Number value for b is: " + implB2.Items.ToList()[0].GetNumberValue());
Console.WriteLine("Date value for b is: " + implB3.Items.ToList()[0].GetDateValue());
Console.WriteLine();
}
}
// Interfaces
public interface IGenericItem
{
int Id { get; set; }
}
public interface IGenericItemA : IGenericItem
{
string GetTextValue();
}
public interface IGenericItemB : IGenericItem
{
int GetNumberValue();
}
public interface IGenericItemC : IGenericItem
{
DateTime GetDateValue();
}
public interface IGenericItems<T>
{
IEnumerable<T> Items { get; }
}
// Classes
public class ConcreteA : IGenericItemA
{
public ConcreteA(int id)
{
Id = id;
}
#region IGenericItemA Members
public string GetTextValue()
{
return Id.ToString();
}
#endregion
#region IGenericItem Members
public int Id { get; set; }
#endregion
}
public class ConcreteB : IGenericItemB
{
public ConcreteB(int id)
{
Id = id;
}
#region IGenericItemB Members
public int GetNumberValue()
{
return Id + 1;
}
#endregion
#region IGenericItem Members
public int Id { get; set; }
#endregion
}
public class ConcreteC : IGenericItemC
{
public ConcreteC(int id)
{
Id = id;
}
#region IGenericItemC Members
public DateTime GetDateValue()
{
return DateTime.Now;
}
#endregion
#region IGenericItem Members
public int Id { get; set; }
#endregion
}
// Implicit interfaces implementation
public class ImplicitClientA : IGenericItems<IGenericItemA>, IGenericItems<IGenericItemB>
{
#region IGenericItems<IGenericItemA> Members
public IEnumerable<IGenericItemA> Items
{
get
{
var collection = new List<IGenericItemA>();
collection.Add(new ConcreteA(1));
return collection;
}
}
#endregion
#region IGenericItems<IGenericItemB> Members
IEnumerable<IGenericItemB> IGenericItems<IGenericItemB>.Items
{
get
{
var collection = new List<IGenericItemB>();
collection.Add(new ConcreteB(1));
return collection;
}
}
#endregion
}
public class ImplicitClientB : ImplicitClientA, IGenericItems<IGenericItemC>
{
#region IGenericItems<IGenericItemC> Members
public new IEnumerable<IGenericItemC> Items
{
get
{
var collection = new List<IGenericItemC>();
collection.Add(new ConcreteC(2));
return collection;
}
}
#endregion
}
// Explicit interfaces implementation
public class ExplicitClientA : IGenericItems<IGenericItemA>, IGenericItems<IGenericItemB>
{
#region IGenericItems<IGenericItemA> Members
IEnumerable<IGenericItemA> IGenericItems<IGenericItemA>.Items
{
get
{
var collection = new List<IGenericItemA>();
collection.Add(new ConcreteA(1));
return collection;
}
}
#endregion
#region IGenericItems<IGenericItemB> Members
IEnumerable<IGenericItemB> IGenericItems<IGenericItemB>.Items
{
get
{
var collection = new List<IGenericItemB>();
collection.Add(new ConcreteB(1));
return collection;
}
}
#endregion
}
public class ExplicitClientB : ImplicitClientA, IGenericItems<IGenericItemB>, IGenericItems<IGenericItemC>
{
#region IGenericItems<IGenericItemB> Members
IEnumerable<IGenericItemB> IGenericItems<IGenericItemB>.Items
{
get
{
var collection = new List<IGenericItemB>();
collection.Add(new ConcreteB(2));
return collection;
}
}
#endregion
#region IGenericItems<IGenericItemC> Members
IEnumerable<IGenericItemC> IGenericItems<IGenericItemC>.Items
{
get
{
var collection = new List<IGenericItemC>();
collection.Add(new ConcreteC(2));
return collection;
}
}
#endregion
}
}
Thanks in advance.
I figured it out.
The answer is no.
For example ImplicitClientA implements IGenericItems<IGenericItemA> and IGenericItems<IGenericItemB>.
Only one of them can be implicitly declared. The other must be explicitly declared. I guess the first is something like decorator to the class.
For the first I can declare the method as virtual and override it in child class ImplicitClientB or I can use a virtual protected method and override this in the child class ImplicitClientB.
So for ImplicitClientA I can refer to Items both like:
var implA = new ImplicitClientA();
var x = implA.Items;
or
IGenericItems<IGenericItemA> implA = new ImplicitClientA();
var x = implA.Items;
but if I want to use the IGenericItems<IGenericItemB> the only way is
IGenericItems<IGenericItemB> implA = new ImplicitClientA();
var x = implA.Items;
Now for the child class ImplicitClientB.
If I want to do something else for IGenericItems<IGenericItemA> Items property, all I have to do, is to declare it virtual in ImplicitClientA and override it. Or use the virtual protected method as I mentioned earlier.
But in order to change the implementation for IGenericItems<IGenericItemB> which is inherited by ImplicitClientA, I have to explicitly implement IGenericItems<IGenericItemB> in ImplicitClientB.
So I can refer to it only with one way:
IGenericItems<IGenericItemB> implB = new ImplicitClientB();
var x = implB.Items;
So everything works and everyone is happy!
I wouldn't explicitly implement the interfaces.
They have already been implemented by ImplicitClientA, so if you do you'd have to be very careful to how you call your method (A implements an interface implicitly, B implements it explicitly):
B b = new B();
b.Method(); // calls the method defined in A
((A)b).Method(); // calls the method defined in A
((IInterface)b).Method(); // calls the method defined in B
I'd say the responsibility of implementing the IGenericItems<IGenericItemA> interface is with ImplicitClientA, so that's the right place to indicate that the functionality can be overridden.
Related
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();
i have an object which have an attribute of Serializable, this class inherit from abstract class which inherit from other class which also Serializable which inherit from an interface
i have used
string included = JsonConvert.SerializeObject(msg,
Formatting.Indented,
new JsonSerializerSettings { /*ContractResolver = new NotificationPropertyResolver()*/ TypeNameHandling = TypeNameHandling.All});
as msg is the interface
I want to send this object in SignalR and i see that it dont ignore any member,
i have decorated the interface and the classes
is there solution for that?
i have tried also to use resolver with my own attributes - but still same results
the classes are to big but ...
[Serializable]
[WebAPINotification(Type = typeof(CSensor), Group = "Sensor")]
public class SensorsStateModeNotification : SensorNotification, IBPMPackagedNotification
public abstract class SensorNotification : BasicLanNotification, ISensNotification
[Serializable]
public class BasicLanNotification : BasicNotification, ILanNotification
[Serializable]
public abstract class BasicNotification : INotification, ISerializable, IOpSerializable
[JsonIgnore]
public long SentAt
{
get
{
return m_sentAt;
}
set
{
m_sentAt = value;
}
}
/// <summary>
///
/// </summary>
[JsonIgnore]
public ENotificationGateway NotificationGateway
{
get
{
return m_NotifyGateway;
}
set
{
m_NotifyGateway = value;
}
}
Your type implements the ISerializable interface - that takes precedence over attributes. If you don't want to serialize the members of the class, simply don't return them in the ISerializable.GetObjectData implementation. See the SSCCE below (and by the way, in the future if you want better answers, you should provide one as well) for an example.
public class StackOverflow_18127665
{
public class WebAPINotificationAttribute : Attribute
{
public Type Type { get; set; }
public string Group { get; set; }
}
public class CSensor { }
public interface INotification { }
public interface IOpSerializable { }
public interface IBPMPackagedNotification { }
public interface ILanNotification { }
public interface ISensNotification { }
[Serializable]
[WebAPINotification(Type = typeof(CSensor), Group = "Sensor")]
public class SensorsStateModeNotification : SensorNotification, IBPMPackagedNotification { }
public abstract class SensorNotification : BasicLanNotification, ISensNotification { }
[Serializable]
public class BasicLanNotification : BasicNotification, ILanNotification { }
[Serializable]
public abstract class BasicNotification : INotification, ISerializable, IOpSerializable
{
long m_sentAt;
ENotificationGateway m_NotifyGateway;
[JsonIgnore]
public long SentAt
{
get
{
return m_sentAt;
}
set
{
m_sentAt = value;
}
}
/// <summary>
///
/// </summary>
[JsonIgnore]
public ENotificationGateway NotificationGateway
{
get
{
return m_NotifyGateway;
}
set
{
m_NotifyGateway = value;
}
}
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
// Comment the lines below not to have this serialized
info.AddValue("NotificationGateway", this.NotificationGateway);
info.AddValue("SentAt", this.SentAt);
}
#endregion
}
public enum ENotificationGateway { First, Second }
public static void Test()
{
BasicNotification msg = new BasicLanNotification
{
SentAt = 123,
NotificationGateway = ENotificationGateway.First
};
var str = JsonConvert.SerializeObject(
msg,
Newtonsoft.Json.Formatting.Indented,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
Console.WriteLine(str);
}
}
public class NotificationPropertyResolver : DefaultContractResolver
{
public NotificationPropertyResolver()
{
IgnoreSerializableAttribute = true;
IgnoreSerializableInterface = true;
}
}
Using this model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
#region Abstracts definitions
abstract class AnAbstract
{
public string Name { get { return this.GetType().Name; } }
public bool IsNumeric { get { return this is ANumericAbstract; } }
public /*abstract*/ string Description = default(string);
}
abstract class ANumericAbstract : AnAbstract
{
public /*abstract*/ double Min = double.MinValue;
public /*abstract*/ double Max = double.MaxValue;
}
abstract class ANonNumericAbstract : AnAbstract
{
public List<Object> objects = new List<Object>();
}
#endregion Abstracts definitions
#region Concrete definitions
class NumericImpl : ANumericAbstract
{
new public const string Description = "A numeric implementation";
new public const double Min = 0;
new public const double Max = 1000;
public NumericImpl()
{
}
}
abstract class AnotherImpl : ANonNumericAbstract
{
public AnotherImpl()
{
objects.Add("one");
objects.Add("two");
objects.Add("three");
}
}
class SideA : AnotherImpl
{
new public const string Description = "Disc side A";
}
class SideB : AnotherImpl
{
new public const string Description = "Disc side B";
}
#endregion Concrete definitions
partial class Parameter
{
public string Name { get; set; }
public string Description { get; set; }
public bool IsNumeric { get; private set; }
public double Min { get; private set; }
public double Max { get; private set; }
public List<Object> Values { get; private set; }
private Parameter()
{
Values = new List<Object>();
}
}
}
With this, I pretend to define a hierarchy of classes for which I can have some abstract properties (Name,Description,IsNumeric) and at the end of the hierarchy there should be some classes which mandatorily define those properties; in the case of ANumericAbstract they should have additional specific properties, e.g. Min and Max.
Now here's the problem.
I'm attemtping to be able to create instances of Parameter which take a generic AnAbstract and read from it some values to fill in the Parameter properties, à la
Parameter<ANumericAbstract> ParamNum = new Parameter<NumericImpl>();
where a Parameter constructor would take in the passed type and "fill in the blanks". In other words, I'm trying something like:
using System;
namespace ConsoleApplication1 {
partial class Parameter
{
public static Parameter NewParameter<T>() where T : AnAbstract
{
Parameter Parameter = new Parameter();
// THESE DON'T WORK:
this.Name = T.Name;
this.Description = T.Description;
this.IsNumeric = T.IsNumeric;
if (this.IsNumeric)
{
this.Min = (T as ANumericAbstract).Min;
this.Max = (T as ANumericAbstract).Max;
}
else
{
foreach(Object val in (T as ANonNumericAbstract).Values)
{
this.Values.Add(val);
}
}
return Parameter;
}
}
class Program
{
private AnAbstract Number = new NumericImpl();
static void Main(string[] args)
{
}
// THESE DON'T WORK:
private static Parameter<ANumericAbstract> ParameterNum =
Parameter.NewParameter<NumericImpl>();
private static Parameter<ANonNumericAbstract> ParameterA =
Parameter.NewParameter<SideA>();
private static Parameter<ANonNumericAbstract> ParameterB =
Parameter.NewParameter<SideB>();
}
}
Obviously the syntax is invalid, but I'm not sure if I'm going in the right direction. Is there some Generics syntax that I'm not using properly? Should I just be done with it and use Getters and Setters à la Java? :-) At this point, just doing the
Parameter par = new Parameter { Name = NumericImpl.Name, /* ... */ };
might seem more sensible...
Firstly you should not use New keyword on your properties.
Consider virtual keyword:
abstract class AnAbstract
{
public virtual string Name { get { return this.GetType().Name; } }
public virtual string Description { get { return String.Empty; } }
}
abstract class ANumericAbstract : AnAbstract
{
public virtual double Min = double.MinValue;
}
class NumericImpl : ANumericAbstract
{
public override string Description { get { return "A numeric implementation"; } }
public override double Min { get { return 0; } }
}
1) You can place an instance of you type in Parameter constructor and have Parameter instance.
partial class Parameter
{
public Parameter(AnAbstract inputObject)
{
this.Name = inputObject.Name;
// etc
}
}
private static Parameter ParameterNum = new Parameter(new NumericImpl());
2) The second way is to use reflection to create an instance of object with initial parameters.
partial class Parameter<T> where T : AnAbstract
{
public static Parameter<T> NewParameter<T>() where T : AnAbstract
{
Parameter<T> parameter = new Parameter<T>();
AnAbstract instance = (AnAbstract)Activator.CreateInstance(typeof(T));
parameter.Name = instance.Name;
// etc
return parameter;
}
}
private static Parameter<NumericImpl> ParameterNum =
Parameter<NumericImpl>.NewParameter();
3) Make Parameter class static and create in via static constructor.
static partial class Parameter<T> where T : AnAbstract
{
public static string Name { get; set; }
//etc
}
static partial class Parameter<T> where T : AnAbstract
{
static Parameter ()
{
AnAbstract instance = (AnAbstract)Activator.CreateInstance(typeof(T));
Parameter<T>.Name = instance.Name;
//etc
}
}
In the last example you can use this class like this:
String someName = Parameter<NumericImpl>.Name;
I'm wondering about what's the way to go, if I need to publicate data-interfaces but want to use them internal with extended calculated properties. To make it clearer:
// The public interface
public interface IData
{
int Property { get; }
}
// The internal interface
internal interface IExtendedData : IData
{
int ExtendedProperty { get; }
}
// The assumed implementation of someone using my interface
public class Data : IData
{
public Data(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public override string ToString()
{
return Property.ToString();
}
}
// My implementation
internal class ExtendedData : IExtendedData
{
public ExtendedData(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
public override string ToString()
{
return Property.ToString() + ExtendedProperty.ToString();
}
}
// publicated by me, for the person who uses my dll
public static class Calculations
{
public static int DoSomeCalculation(IData data, int parameter)
{
// This probably don't work, but maybe shows what I want to do
IExtendedData tempData = (ExtendedData)data;
return tempData.ExtendedProperty * parameter;
}
}
I'm realy frustrated, cause I feel like missing some basical programing skills.
You could solve this problem by implementing ExtendedData as a Wrapper for a class implementing IData
internal class ExtendedData : IExtendedData
{
private IData data;
public ExtendedData(IData data)
{
this.data = data;
}
public int Property
{
get { return data.Property; }
private set { data.Property = value; }
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
}
and use this in DoSomeCalculation like
IExtendedData tempData = new ExtendedData(data);
ExtendedData could inherit from Data:
class ExtendedData : Data
{...}
And for creation of a Data object you add a factory like so:
public class DataFactory
{
public IData CreateData()
{
return new ExtendedData();
}
}
User have to create all its Data objects by this factory. You can ensure it by making Data's constructor internal.
In your DLL you can then cast to ExtendedData.
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)
{
}
}