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)
{
}
}
Related
I have the following code:
public interface BaseInterface
{
int ID { get; }
}
public interface SpecialInterface1 : BaseInterface
{
int price { get; }
}
public interface SpecialInterface1 : BaseInterface
{
int xyz { get; }
}
public class Implementation1 : SpecialInterface
{
int price { get; }
int ID { get; internal set; }
}
public class Implementation2 : SpecialInterface
{
int xyz { get; }
int ID { get; internal set; }
}
Now in a Management class I want to add the objects that implement BaseInterface into a List.
I know that I can use as or is to cast the interface to an implementation, but in my project, I have about 10 special interfaces with an implementation each so I would have to write a really big if statements.
public void Add(BaseInterface u, int id)
{
if (u is Implementation1)
{
((Implementation1)u).ID = id;
Units.Add(u);
}
if (u is Implementation2)
{
((Implementation2)u).ID = id;
Units.Add(u);
}
}
My goal is that the id is not changeable outside the implementation and I would provide only the interfaces outside my dll so none can change the id.
A solution would be to add an extra interface. This eliminates the internal setter in your implementation.
internal interface IChangeID
{
void SetID(int id);
}
public interface IBaseInterface
{
int ID { get; }
}
public class Implementation : IBaseInterface,
IChangeID
{
public void SetID(int id) { ID = id; }
public int ID { get; private set; }
}
Only the real implementations should implement IChangeID. Returning IBaseInterface or ISpecialInterface will hide the setter, because those interfaces do not inherit from IChangeID.
This would change your add into:
public void Add(BaseInterface u, int id)
{
((IChangeID)u).SetID(id);
Units.Add(u);
}
If you do want to return the concrete types, not interfaces. You could implement the given interface explicit. This will hide the set method even from the concrete implementation.
public class Implementation : IBaseInterface,
IChangeID
{
void IChangeID.SetID(int id) { ID = id; }
public int ID { get; private set; }
}
var obj = new Implementation();
obj.SetID() // This WILL NOT Compile
If you don't want to modify the interfaces and implementations, you could use C# 7's pattern matching to access the implementation type without casting. It requires 3 lines per implementation type but avoids modifying the classes:
public void Add(BaseInterface u, int id)
{
switch(u)
{
case Implementation1 u1:
u1.ID = id;
break;
case Implementation2 u1:
u1.ID = id;
break;
default :
throw new ArgumentException("Unexpected implementation!");
}
Units.Add(u);
}
The obvious disadvantage is that the code will have to be modified if a new implementation is added.
Another option is to use dynamic, losing type safety. This will fail at runtime if some implementation doesn't have a setter (eg because it was replaced by constructor initialization)
public void Add(BaseInterface u, int id)
{
dynamic x =u;
x.ID=id;
Units.Add(x);
}
While I like this answer the best,
I recommend making the ID a required parameter of all the implementation's constructors, and then to use a factory pattern to generate any instance you require. This makes any instance without the ID set throw an exception at compile time rather than runtime reducing the probability of exceptions.
Here is a simple example that gets you what you want without an additional interface. Should you choose you can combine my answer with #Iqon's answer.
public interface IInterface
{
int ID { get; }
}
internal class InternalImplementation: IInterface {
public InternalImplementation(int ID) { this.ID = ID; }
public int ID { get; set; }
}
public class MyImplementationFactoryService {
public IInterface Create() {
int id = 1 // Or however you get your ID, possibly from a DB query?
return new InternalImplementation(id);
}
public IInterface Create(type|enum createtype) {
// return type based on typeof or enum
}
}
In case you want to use reflection to set property, code below may help
public interface IBaseInterface
{
int ID { get; }
}
public class Impl1 : IBaseInterface
{
public int ID { get; internal set; }
public int Price {get; set;}
}
public class Impl2 : IBaseInterface
{
public int ID { get { return 0;} }
public int Subscription {get; set;}
}
public class Program
{
public static void Main(string[] args)
{
IBaseInterface obj1 = new Impl1();
SetProperty(obj1, "ID", 100);
Console.WriteLine("Object1 Id is {0}", obj1.ID);
IBaseInterface obj2 = new Impl2();
SetProperty(obj2, "ID", 500);
Console.WriteLine("Object2 Id is {0}", obj2.ID);
}
private static void SetProperty(IBaseInterface obj, string propertyName, object id){
if(obj.GetType().GetProperty(propertyName).CanWrite) {
obj.GetType().GetProperty(propertyName).SetValue(obj, id);
Console.WriteLine("CanWrite property '{0}' : {1}" , propertyName, obj.GetType().GetProperty(propertyName).CanWrite);
}
}
}
Output
CanWrite property 'ID' : True
Object1 Id is 100
Object2 Id is 0
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.
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();
}
how to implement a const field which in subClasses must be overwrite, i'm using .net 4, C#
because i have many classes they all have a const field(with different value) called 'pName'.
so i want use a interface or abstract class or somthing as a parent and force these classes to override it.
it's CONST field
You cannot override a const; nor can you declare it as static and override it there. What you can do is re-declare it, but that is not robust - in that which version gets used depends on which you ask for (entirely at compile-time - completely unrelated to polymorphism):
public new const int Foo = 12;
I would suggest you use a virtual or abstract property:
public virtual int Foo { get { return 4; } } // subclasses *can* override
public abstract int Foo { get; } // subclasses *must* override
and override:
public override int Foo { get { return 12; } }
You request is contradictional: you can not define a constant value which is possible to override, so change in derived class.
What you can do is define default value in base class, and override it in derived one.
public class Base
{
public static reaondly int DEFAULT_BASE_VALUE = 0,
private int _someValue = DEFAULT_BASE_VALUE; //ASSIGN DEFAULT VALUE
public virtual int SomeValue {
get {
return _someValue;
}
}
}
public class Derived : Base
{
public override int SomeValue {
get {
return -3; //CHANGE VALUE OF BASE CLASS
}
}
}
You can't. What you can do is declare a abstract readonly property like so
abstract class A
{
public abstract int ReadOnlyProp {get;}
}
class B : A
{
public override int ReadOnlyProp
{
get { return 42; }
}
}
You can't, constants aren't virtual members.
What you could do instead is have a readonly property e.g
public class BaseClass
{
public BaseClass()
{
}
protected int MyProperty { get { return 10; } }
}
public class DerivedClass : BaseClass
{
public DerivedClass()
{
}
protected override int MyProperty { get { return 20; } }
}
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.