Is there a way i can have derived classes override the default value of the base class? In the example below i would need the Hammer.Name to return "Hammer".
public class ItemBase
{
public string Name = "Base";
}
public class Hammer: ItemBase
{
new public string Name = "Hammer";
}
public class Test
{
ItemBase MyThing = new Hammer();
// Prints "Base"
Console.WriteLine(ItemBase.Name);
}
You don't need different fields, you need different initializations of the same field.
class Base {
protected string name = "";
public Base() { name = "X"};
}
class Derived : Base {
public Derived() { name = "Y"}; //same {name } field of a Base class
}
You might consider using virtual properties instead of exposing public fields (which is considered bad practice).
As such, you can (with C# 6.0):
void Main()
{
ItemBase myThing = new Hammer();
// Doesn't print "Base"
Console.WriteLine(myThing.Name);
}
public class ItemBase
{
public virtual string Name { get; } = "Base";
}
public class Hammer : ItemBase
{
public override string Name { get; } = "Hammer";
}
or (if you're using older version of C#)...
public class ItemBase
{
public virtual string Name { get { return "Base"; } }
}
public class Hammer : ItemBase
{
public override string Name { get { return "Hammer"; } }
}
You are not defining a new default value in the derived type, you are declaring a completely new field that hides the field with the same name in the base class.
Because fields can't be virtual, the returned field is the one declared in the type through which you are invoking it.
Solution? Don't redeclare a new field, simply assign a new value to the existing field in the constructor of the derived type:
public class Hammer
{
public Hammer() {
Name = "Hammer"; }
}
Trying to figure out what exactly is needed while skating around the .NET version restrictions has been a headache but I have a solution. According to your comments you can use a constructor.
In that case this is really easy to do with properties (which are the preferred way to handle your situation) instead of public fields:
public class ItemBase
{
public ItemBase()
{
//When instantiating ItemBase the value of Name is "Base"
Name = "Base";
}
public string Name { get; set; }
}
public class Hammer : ItemBase
{
public Hammer()
{
//When instantiating Hammer the value of Name is "Hammer"
Name = "Hammer";
}
}
And to test just run this:
public class Program
{
public static void Main()
{
ItemBase itemBase = new Hammer();
Console.WriteLine(itemBase.Name);
itemBase.Name = "Foo";
Console.WriteLine(itemBase.Name);
}
}
Outputs:
Hammer
Foo
This should check off all the boxes. You now use properties (making your code better), each class has a default value, and the properties can be changed after instantiation.
I have a class structure with a base abstract class with derived classes.
My base class looks like this:
public abstract class Graph
{
public Dictionary<Vector3, int> Dictionary { private set; get; }
public List<T> List { set; get; }
public Graph()
{
Dictionary = new Dictionary<Vector3,int>();
}
}
Then i have 2 derived classes:
public class Graph_Waypoints : Graph
{
public Graph_Waypoints() : base ()
{
List = new List<Waypoint>();
}
}
public class Graph_Tiles : Graph
{
public Graph_Tiles() : base ()
{
List = new List<Tile>();
}
}
But it seems i cannot do flexible types for my graph like this. The idea here is to create a graph that lets me use different objects for its nodes. Whether it be a way-point graph or a tile based graph.
But i am struggling to work out how to get the flexibility for it to allow me change the type when i create each new graph.
Am i going in the right direction here ? How can i get the type flexibility on my list?
You're nearly there; you're just missing some key parts:
public abstract class Graph<T> // <-- Graph must be generic
{
public Dictionary<Vector3, int> Dictionary { private set; get; }
public List<T> List { set; get; }
public Graph()
{
Dictionary = new Dictionary<Vector3, int>();
// You could initialize the list as you did before, but it's cleaner to do it here
List = new List<T>();
}
}
public class Graph_Waypoints : Graph<Waypoint> // <-- Subclasses must provide the base class generic arguments
{
public Graph_Waypoints() : base()
{
}
}
public class Graph_Tiles : Graph<Tile>
{
public Graph_Tiles() : base()
{
}
}
Also note, you do not need to explicitly write : base() when implementing argument-less constructors; the compiler does it for you
Ok so, I've run into an interested and probably simple problem. I have a base class that is inherited by another class (child). I have the same parameterless constructor in the base and the child. I would like to set defaults in the child that propagate into the base properties. I would like to do something like this:
public partial class baseclass
{
public baseclass() {
//never called if instantiated from baseclass(string newp1)
p1 = "";
p2 = "google";
}
public baseclass(string newp1) {
p1 = newp1; //p2 will be "" and p1 will be newP1
}
public string p1 { get; set; }
public string p2 { get; set; }
}
public partial class childclass : baseclass
{
public childclass() {
//How can I call this to set some default values for the child?
p2 = "facebook";
}
public childclass(string newp1) : base(newp1) {
p1 = newp1; //p2 needs to be "facebook"
}
}
Use constructors chaining if you have duplicated code in several constructors:
public class baseclass
{
public baseclass() : this("google") { }
public baseclass(string newp1)
{
p1 = newp1; // the only place in your code where you init properties
p2 = "";
}
public string p1 { get; set; }
public string p2 { get; set; }
}
Child class should inherit baseClass
public class childclass : baseclass
{
public childclass() : this("facebook") { } // you can also call base here
public childclass(string newp1) : base(newp1) { }
}
Also keep in mind that parital just allows you split class/method definiton in several parts (e.g. keep it in different files). It is useful when you are generating classes (e.g. from database tables) but still want to add/customize something in generated classes. If you will put customized code directly into generated files, then it will be lost after classes re-generation. Read more
You can create a protected constructor in base class and call it in child class:
public class Base
{
public Base(int value1, int value2) { ... }
protected Base(string value1) { ... } // only for child class
}
public class Child : Base
{
public Child() : Base("Value") { ... }
}
I have a couple abstract classes, and would like to make sure that the "Manager" is always registered with the "Managed" class such that they retain a two-way knowledge of the one-to-many relationship. That is, the Manager knows all of the Managed classes it has, and the Managed class knows who its Manager is (if it is registered with one). Further, I'd like the managed class to be able to call the specialization of its concrete manager without having to do a special cast. Is that possible?
I'd like something like this, but run into compilation issues:
class Program
{
static void Main(string[] args)
{
ConcreteManager manager = new ConcreteManager();
ConcreteManaged managed = new ConcreteManaged() { Name = "Test" };
manager.Add(managed);
managed.Process();
}
}
public abstract class BaseManager<ManagedType>
where ManagedType : BaseManaged
{
protected Dictionary<string, ManagedType> registered = new Dictionary<string, ManagedType>();
public void Add(ManagedType managed)
{
managed.Manager = this; // Cannot implicitly convert type 'BaseManager<ManagedType>' to 'BaseManager<BaseManaged>' (I've tried casting to no avail)
registered.Add(managed.Name, managed);
}
// Other common management tasks
}
public class ConcreteManager : BaseManager<BaseManaged>
{
//specialization stuff, e.g.
public void Refresh() { Console.WriteLine("Refresh Called"); }
}
public abstract class BaseManaged
{
public string Name { get; set; }
public BaseManager<BaseManaged> Manager { get; set; }
}
public class ConcreteManaged : BaseManaged
{
//specialization stuff, e.g.
public void Process()
{
Manager.Refresh();
}
}
If I change the non Program classes around a bit, as follows, I can get it to compile, but there are runtime errors (Unable to cast object of type 'TestAbstractGenerics.ConcreteManager' to type 'TestAbstractGenerics.IBaseManager`1[TestAbstractGenerics.IBaseManaged]'.):
public interface IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
void Add(ManagedType service);
}
public abstract class BaseManager<ManagedType> : IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
protected Dictionary<string, ManagedType> registered = new Dictionary<string, ManagedType>();
public void Add(ManagedType managed)
{
managed.Manager = (IBaseManager<IBaseManaged>)this;
registered.Add(managed.Name, managed);
}
// Other common management tasks
}
public class ConcreteManager : BaseManager<BaseManaged>
{
//specialization stuff, e.g.
public void Refresh() { Console.WriteLine("Refresh() called"); }
}
public interface IBaseManaged
{
string Name { get; set; }
IBaseManager<IBaseManaged> Manager { get; set; }
}
public abstract class BaseManaged : IBaseManaged
{
public string Name { get; set; }
public IBaseManager<IBaseManaged> Manager { get; set; }
}
public class ConcreteManaged : BaseManaged
{
//specialization stuff, e.g.
public void Process()
{
((ConcreteManager)Manager).Refresh();
}
}
If I change the IBaseManager<IBaseManaged> to dynamic I can remove the cast from Process() and everything works as expected, but dynamic doesn't work with intellisense, and I would like to be able to enforce the type checking (so an implementer can't accidentally set Manager to a string, for example). So what's the best practice here? Is there a good pattern to follow that allows me to preserve the one-to-many relationship?
And yes, in the above I'd have to add some logic to make sure that when BaseManaged.Manager is set that it unregisters from its current Manager, if any. I avoided that here for sake of simplicity.
Edit: this works, but still requires casting to the ConcreteManager prior to calling its non-interface methods:
class Program
{
static void Main(string[] args)
{
var manager = new ConcreteManager();
var managed = new ConcreteManaged() { Name = "Test"};
manager.Add(managed);
managed.Process();
}
}
public interface IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
void Add(ManagedType managed);
}
public abstract class BaseManager<ManagedType> : IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
protected Dictionary<string, ManagedType> registered = new Dictionary<string, ManagedType>();
public void Add(ManagedType managed)
{
managed.Manager = (IBaseManager<IBaseManaged>)this;
registered.Add(managed.Name, managed);
}
// Other common management tasks
}
public class ConcreteManager : BaseManager<IBaseManaged>
{
//specialization stuff, e.g.
public void Refresh() { Console.WriteLine("Refresh() called"); }
}
public interface IBaseManaged
{
string Name { get; set; }
IBaseManager<IBaseManaged> Manager { get; set; }
}
public abstract class BaseManaged : IBaseManaged
{
public string Name { get; set; }
public IBaseManager<IBaseManaged> Manager { get; set; }
}
public class ConcreteManaged : BaseManaged
{
//specialization stuff, e.g.
public void Process()
{
((ConcreteManager)Manager).Refresh();
}
}
I'm pretty sure the kind of cyclic relationship you want is not possible to implement perfectly type safe and without casts, because the compiler would end up getting into infinite cycles if you wanted IBaseManaged also to be generic (ie, IBaseManaged<T> where T : IBaseManager<?>), is clearly not possible to specify the constraint you need in place of ?.
You can however, create a third interface/class which can fully express this kind of circular constraint, which might provide an alternative solution.
interface IManagerAdapter<TManager, TManaged>
where TManager : IBaseManager<TManaged>
where TManaged : IBaseManaged<TManager>
IMO, if your ConcreteManaged class is going to know directly about ConcreteManager by virtue of the type cast anyway, these classes don't really provide much more than a pattern to follow for concrete types, the abstraction is kind of broken. If you need this tight coupling between the specific concrete manager and managed types anyway, I would probably make it explicity by adding the specific type in place of Managed in each class, and do away with the BaseManaged class, which doesn't help very much other than providing the Name, which is simple enough to re-implement in concrete instances.
public interface IBaseManaged<T> {
string Name { get; set; }
T Manager { get; set; }
}
public class ConcreteManaged : IBaseManaged<ConcreteManager> {
public string Name { get; set; }
public ConcreteManager Manager { get; set; }
public void Process ()
{
Manager.Refresh ();
}
}
For anything in the base types which might be more complex to implement than Name, I would opt for a Mixin like approach, where you implement that additional functionality in a separate class, and just provide a property in the interface to retreive the Mixin. For example, if all the Manager classes need to account for registering all of the Managed (as with your Add()), you obviously don't want to duplicate that functionality in each Manager - but you could simplify the approach by implementing some ManagedRegister<T> type, say (can be whatever you like), and giving the IBaseManager type a Registered field to retreive an instance.
public interface IBaseManager<T> {
ManagedRegister<T> Registered { get; set; }
}
public class ConcreteManager : IBaseManager<ConcreteManaged> {
public ManagedRegister<ConcreteManaged> Registered { get; set; }
public void Refresh () { Console.WriteLine("Refresh() called"); }
}
You still get a strongly typed Managed instances from the Register inside the Manager here.
The change from your calling code is that instead of manager.Add(managed), it becomes manager.Registered.Add(managed), and you also need to create an instance of ManagedRegister<ConcreteManaged> to pass to the ConcreteManager.. Perhaps a bit messy, and I would suggest abstracting that away into a factory, which will prevent simple mistakes like forgetting to add managed instances to the manager. We can use that circular constraint from above to implement it in a type safe way. (And if it's possible to assume every Managed/Manager has a parameterless constructor, a single implementation will work by using new() constraints. Otherwise you'll want an abstract factory and implement for each concrete type).
interface IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>
where TManaged : IBaseManaged<TManager>
{
TManager Manager { get; }
TManaged Create (string name);
}
public abstract class ManagerFactory<TManager, TManaged>
: IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>, new()
where TManaged : IBaseManaged<TManager>, new()
{
TManager manager = new TManager ();
public ManagerFactory () {
manager.Registered = new ManagedRegister<TManaged> ();
}
public TManager Manager { get { return manager; } }
public TManaged Create (string name)
{
TManaged result = new TManaged ();
result.Name = name;
manager.Registered.Add (result.Name, result);
result.Manager = manager;
return result;
}
}
public class ConcreteFactory
: ManagedFactory<ConcreteManager, ConcreteManaged> { }
Back to Main, the usage is slightly simplified here.
ConcreteFactory f = new ConcreteFactory ();
ConcreteManaged managed = f.CreateManaged ("Test");
managed.Process ();
EDIT:
Here's abstracting all of the common functionality into so called "Base classes". The key difference here is that the Base classes composed into the concrete class rather than inherited, by means of the Base property, which acts very much like the base. prefix you'd use to call base members usually.
public class BaseManager<T> {
public Dictionary<string, T> Registered { get; set; }
}
public interface IBaseManager<T> {
BaseManager<T> Base { get; set; }
}
public class ConcreteManager
: IBaseManager<ConcreteManaged> {
public BaseManager<ConcreteManaged> Base { get; set; }
public void Refresh() { Console.WriteLine("Refresh() called"); }
}
public class BaseManaged<T> {
public string Name { get; set; }
public T Manager { get; set; }
}
public interface IBaseManaged<T> {
BaseManaged<T> Base { get; set; }
}
public class ConcreteManaged
: IBaseManaged<ConcreteManager> {
public BaseManaged<ConcreteManager> Base { get; set; }
internal ConcreteManaged () { }
public void Process () {
Base.Manager.Refresh ();
}
}
interface IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>
where TManaged : IBaseManaged<TManager> {
TManager Manager { get; }
TManaged Create (string name);
}
public abstract class BaseManagerFactory<TManager, TManaged>
: IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>, new()
where TManaged : IBaseManaged<TManager>, new() {
TManager manager = new TManager();
public BaseManagerFactory() {
manager.Base = new BaseManager<TManaged>();
manager.Base.Registered = new Dictionary<string, TManaged>();
}
public TManager Manager { get { return manager; } }
public TManaged Create (string name) {
TManaged result = new TManaged();
result.Base = new BaseManaged<TManager>();
result.Base.Name = name;
manager.Base.Registered.Add (name, result);
result.Base.Manager = manager;
return result;
}
}
public interface IHasFeature<TFeature> {
TFeature Feature { get; set; }
}
public class FeatureOne {
/*...*/
}
public class ProductOne : IHasFeature<FeatureOne> {
public FeatureOne Feature { get; set; }
}
public abstract class BaseContainer<TProduct, TFeature>
where TProduct : IHasFeature<TFeature> {
public TProduct Product { get; set; }
public void DoProcess() {
var result = Product.Feature.Execute(); //Execute is an extension method
}
}
public class MyContainer : BaseContainer<ProductOne, FeatureOne> {
/*...*/
}
Works when I do:
MyContainer : BaseContainer<ProductOne, FeatureOne>
But I want to:
MyContainer : BaseContainer<ProductOne>
ProductOne : IHasFeature<...> should already contain the nested generic feature TFeature, I don't want to repeat them again in MyContainer construction.
Any idea how I can improve this? Thanks.
EDIT2 -----------------------
Removed new keyword, it was wrong as Nenad said.
The compile translates your call to the extension method Execute() as a call to the static method of the class where it is defined. So, when you call Product.Feature.Execute() inside DoProcess(), the compiler needs to know the type of Product.Feature in order to call the appropriate extension method.
What I suggest is write IHasFeature like this
public interface IHasFeature
{
void DoSomethingWithFeature();
}
If you want to keep IHasFeature generic, the best you can do is define BaseContainer without specifying TFeature and implement DoProcess() in MyContainer.
public abstract class BaseContainer<TProduct>
{
public TProduct Product { get; set; }
public abstract void DoProcess();
}
public class MyContainer : BaseContainer<ProductOne>
{
public override void DoProcess()
{
Product.Feature.Execute();
}
}