i got a problem with overwriting a property which comes from an Interface. I got one Base Class which implements an Interface. This class has arround 10 Subclasses. The subclasses should overwrite the property which comes from the Interface in some cases.
My problem is, that i access the property while not knowing what type of class the object has and the object allways returns the base class property value instead of the overwritten subclass property value.
Example Code simplified:
public interface Inf
{
string Info
{
get;
}
}
public class BaseClass : Inf
{
public string Info
{
get { return "Something"; }
}
}
public class SubClass : BaseClass
{
new public string Info
{
get { return "Something else"; }
}
}
in another class i have to access the property, i dont know if the object is type of base or subclass at this moment
List<BaseClass> listBase = new List<BaseClass>();
listBase.Add(new BaseClass());
listBase.Add(new SubClass());
foreach (BaseClass obj in listBase)
{
Console.WriteLine(obj.Info);
}
Output:
Something
Something
wanted output:
Something
Something else
((SubClass)obj).Info would output "Something else"
but at this certain moment i dont know what kind of class the object is. (i have arround 10 different subclasses).
Do i have to cast all objects to it's real class? i got like 100-200 objects in this list and arround 10 different classes. Or is there any other way to do this?
any help appreciated :)
You should make the property implementation virtual in the base class, and put override instead of new on the implementations in derived classes. This should fix the problem.
Currently, the only class that provides the implementation for the property Info from the interface Inf is your BaseClass. According to your code, compiler thinks that the derived class SubClass introduces a new property with the same name, which is legal. Such property would be accessible only when you use the class directly, not through an interface.
You have broken the chain by "new"ing the property. You need to override it:
public interface Inf
{
string Info
{
get;
}
}
public class BaseClass : Inf
{
public virtual string Info
{
get { return "Something"; }
}
}
public class SubClass : BaseClass
{
public override string Info
{
get { return "Something else"; }
}
}
You're doing it wrong. Do following:
declare base class property using virtual keyword
add override keyword next to subclass property declaration
public class BaseClass : Inf
{
public virtual string Info
{
get { return "Something"; }
}
}
public class SubClass : BaseClass
{
public override string Info
{
get { return "Something else"; }
}
}
With that the result is as you expect.
Read more about overriding and polymorphism here: Polymorphism (C# Programming Guide)
Related
Thanks ahead, community!
As the title describes, I would like to cast an object that is in parent type to a child type, which is actually a child type, whilst this 'specific type' cannot be known until runtime.
Lets say I have following data holder:
public class Holder {}
public class Holder<T> : Holder
{
public T Value;
}
And this Holder (not Holder<T>) will be given to some script at runtime.
I need to cast this Holder into Holder<T> (eg, Holder<string>), so that I can access the Value : T.
For now, I can just mannually add casting cases and their coresponding methods to process it, but time by time there will be more types that goes into this Holder<T>, and it would become imposible to manage in this way.
Is there a way to accomplish this objective?
This Holder must not be flattened, as it is being used in a context as below:
public class SomeNode
{
protected Holder holder;
}
public class SomeNode<T> : SomeNode
{
public SomeNode<T>()
{
holder = new Holder<T>();
}
}
I have no clue how to approach this, nor a search keyword to catch a hint about this.
Automatic suggestions came up before posting seems not my case, which were:
C# Create (or cast) objects of a specific type at runtime
C# Accessing generic Method without knowing specific type
Edit
Thanks to #W.F., I could start searching with an effective keyword 'dynamic object', and I ended up finding System.Reflection as my desired soultion.
It looks like as belows and currently it solves my immediate issue:
holder.GetType().GetProperty("GetValue").Invoke(holder, null);
But as pointed out by #OlivierJacot-Descombes, my structure and a way of using it is breaking a purpose of polymorphism. Therefore I still need a better solution, which would do a job I am looking for and also not breaking polymorphism.
Possible walkaround that comes in my head is that, first, create a method GetValue() in Holder, and also create class that inherits from Holder to implement this method:
public class Holder
{
public virtual string GetValue() => "";
}
public class Holder<T> : Holder
{
public T Value;
}
public class FloatHolder : Holder<float> //for example
{
public override string GetValue() => Value.ToString();
}
Second, change node structure like:
public class SomeNode
{
protected Holder holder;
}
public class SomeNode<T> : SomeNode {}
public class FloatNode : SomeNode<float>
{
public FloatNode()
{
holder = new FloatHolder();
}
}
Then, I can do like:
public class EchoNode : SomeNode
{
public void Tick()
{
Console.WriteLine(holder.GetValue());
}
}
Seems like too many classes are being created, but it also seems not breaking polymorphism.
Looking for further advices. Again, Thanks!
Edit#2
I already said this in the comment, but for better readability, I write this here as well.
Both Dynamic Object and System.Reflection were easy and fitting solutions which I was looking for, but they weren't best solutions in general.
At the beginning I was misinterpreting #OlivierJacot-Descombes 's answer. He was overall pointing out two impediments: first, my class structure is breaking polymorphism, and second, reflection is slow (and later I noticed, dynamic object as well). I didn't catch the last bit at first so I went through a long way.
Moreover, turned out, I couldn't use dynamic object for my project context, as I am not using normal C# but a Unity C#. Technically I can, but they don't blend well.
Thankfully, my revised solution was acceptable. Therefore I decided to select #OlivierJacot-Descombes 's post as an answer. But I hope, still, people would approach and leave me an good advices.
Thank you all.
If you need to cast to a specific type, you are doing polymorphism wrong. Of course you could do something like this:
switch (holder)
{
case Holder<string> stringHolder:
DoStringThing(stringHolder.Value);
break;
case Holder<int> intHolder:
DoIntThing(intHolder.Value);
break;
...
}
See also: Switch statements with patterns.
However, the idea behind polymorphism is to be able to do things without having to know the specific type. Therefore, re-design the holder classes and have them do the type specific thing themselves:
public abstract class Holder
{
public abstract void DoThing();
}
public abstract class Holder<T> : Holder
{
public abstract T Value { get; }
}
Some examples of specific types:
public class StringHolder : Holder<string>
{
public StringHolder(string value)
{
Value = value;
}
public override string Value { get; }
public override void DoThing()
{
Console.WriteLine($"String of length {Value.Length} is \"{Value}\"");
}
}
public class IntHolder : Holder<int>
{
public IntHolder(int value)
{
Value = value;
}
public override int Value { get; }
public override void DoThing()
{
Console.WriteLine($"The integer {Value} is {(Value % 2 == 0 ? "even" : "odd")}");
}
}
Now you can simply write
holder.DoThing();
... without having to cast.
Update
Your edited question indeed shows a polymorphic version.
Here I want to present another approach which merges Holder and Holder<T> in a single class through the use of interfaces.
public interface IHolder
{
object Value { get; set; }
}
public interface IHolder<T> : IHolder
{
new T Value { get; set; } // The new keyword hides the inherited property.
}
public class Holder<T> : IHolder<T>
{
object IHolder.Value
{
get => Value; // Returns T Holder<T>.Value as object.
set => Value = value is T t ? t : default; // Sets T Holder<T>.Value.
}
public T Value { get; set; }
}
Holder<T> now implements a "neutral" Value property declared in IHolder based on the object type. Since it implements it explicitly (i.e., instead of public object Value we write object IHolder.Value), this property is hidden, unless it is accessed through the interface. This allows you, for example, to declare a List<IHolder> and to retrieve different kinds of Holder<T> values with list[i].Value as object.
But you have a variable Holder<float> floatHolder, you can get the strongly typed float value.
Note that this still allows you do derive more specific types like class FloatHolder : Holder<float>, but it might not even be necessary.
If you intend to work only with derived types, you can mark Holder<T> as abstract and also all the members that must be implemented by the deriving classes. This makes it impossible to create an instance of Holder<T> with new and also allows you to declare abstract methods without body.
community! It's a good question. That was interesting.
I think this is simple solve for this question.
We just need to create a simple constructor like below
public class Holder
{
public string SomeData; // just example data
public Holder()
{
}
public Holder(Holder someData)
{
SomeData = someData.SomeData;
}
}
public class Holder<T> : Holder
{
public T Value;
public Holder(Holder a, T t = default)
:base(a)
{
Value = t;
}
}
public class Programm
{
void Main()
{
var h = new Holder();
var g = new Holder<string>(h);
}
}
this might be a easy question but I am struggling with it.
I have two classes that are derived from a base class
class Base
{
public int BaseProperty;
...
}
class A: Base
{
public int Property_derived;
...
}
Class B: Base
{
public int Property_derived;
...
}
Now I have a UI form, that got a textbox that should display the property of derived class(I assure the number and datatypes of properties of all derived classes would be same)
I have done something like:
textbox1.text = objectA.Property_derived;
how do I change it to make it more generic like:
textbox1.text = objecttypedoesntmatter.Property_derived;
so that I should be able to use the same user interface for any derived class.
Any help much appreciated.
Many Thanks
What you need to do is define your Property_derived in the base class, and thus have it as part of the shared contract of all derived classes. Polymorphism, a property of inheritance, will call the derived, overridden property. Note, though, that this will work for a property, not a field:
class Base
{
public virtual int MyProperty {get { return 1;} }
}
class A: Base
{
public override int MyProperty { get { return 5; } }
}
class B: Base
{
public override int MyProperty { get { retun 7; } }
}
Main Question:
I have a reference type (object/class) where I would like to specify accessors' implementation details, but I don't want the type to be instantiable, only extendible.
Abstract Classes don't allow bodies to the accessors of Properties as far as I understand, so that makes it trouble some for me.
How would I go about this in the most 'correct' and elegant manner?
Second question:
I would also like functionality for overloading accessors if there is a way? One reason is that I have an enum Property, which I want to be settable by using its value (int) or its enum reference type.
Abstract Classes don't allow bodies to the accessors of Properties as far as I understand
Yes they do... this is perfectly legal
abstract class MyBaseClass
{
private int _myProperty;
public int MyProperty
{
get { return _myProperty; }
set { _myProperty = value; }
}
}
Perhaps you're confusing abstract classes and interfaces; interfaces can declare members, but they can't provide an implementation for those members.
Abstract Classes don't allow bodies to the accessors of Properties as
far as I understand, so that makes it trouble some for me.
yes they do;
public abstract class Foo
{
public string Prop
{
get { return "yesTheyDo"; }
}
}
are you marking them abstract?
I think this should do what you want:
public abstract class MyParentClass
{
public enum MyEnum
{
one,
two,
three
}
private MyEnum _enumeration;
public string Name { get; private set; }
public MyEnum Enumeration { get { return this._enumeration; } }
public void SetEnumeration(string value)
{
// ... do something
}
public void SetEnumeration(MyEnum value)
{
// ... do something
}
}
There are two overloaded methods for setting the Enumeration property and some methods have their bodies declared whilst the whole class cannot be instantiated.
Hope that helps :)
You can define the body of methods and properties inside of an abstract class. The abstract part of it essentially just prevents it from being instantiated. To accomplish this, you would write the property as normal:
public string Name
{
get { return "SomeName"; }
}
As an example. As for allowing overloading of accessors, you could do one of the following:
// By setting this as 'virtual' you can allow classes that inherit from this to override the functionality if they so wish
public virtual string Name
{
get { return "SomeName"; }
}
// or
public virtual string GetName()
{
return "SomeName";
}
One tip: if you are wanting the functionality to be overridden and accessible only to classes that inherit the abstract class, use the protected keyword:
protected virtual void DoSomething() { }
In C#, using reflection, is it possible to define method in the base class that returns its own name (in the form of a string) and have subclasses inherit this behavior in a polymorphic way?
For example:
public class Base
{
public string getClassName()
{
//using reflection, but I don't want to have to type the word "Base" here.
//in other words, DO NOT WANT get { return typeof(Base).FullName; }
return className; //which is the string "Base"
}
}
public class Subclass : Base
{
//inherits getClassName(), do not want to override
}
Subclass subclass = new Subclass();
string className = subclass.getClassName(); //className should be assigned "Subclass"
public class Base
{
public string getClassName()
{
return this.GetType().Name;
}
}
actually, you don't need to create a method getClassName() just to get the type-name. You can call GetType() on any .Net object and you'll get the meta information of the Type.
You can also do it like this,
public class Base
{
}
public class Subclass : Base
{
}
//In your client-code
Subclass subclass = new Subclass();
string className = subclass.GetType().Name;
EDIT
Moreover, should you really need to define getClassName() in any case, I'd strongly suggest to make it a property [as per .net framework design guide-lines] since the behavior of getClassName() is not dynamic and it will always return the same value every-time you call it.
public class Base
{
public string ClassName
{
get
{
return this.GetType().Name;
}
}
}
EDIT2
Optimized version After reading comment from Chris.
public class Base
{
private string className;
public string ClassName
{
get
{
if(string.IsNullOrEmpty(className))
className = this.GetType().Name;
return className;
}
}
}
I have a class structure for a role playing game which looks like this...
public abstract class Item
{
public abstract string Name { get; set; }
}
public abstract class Armor : Item
{
public override string Name { get; set; }
}
public class Helmet : Armor
{
public override string Name { get; set; }
}
Basically, I am trying to force every derived type to include a "Name" property. Is this the best way to do it? I know I can remove "abstract" from Item.Name and then remove the overriden "Name" properties in Armor and Helmet. If I do that the code looks a little cleaner but I might forget to set the base.Name in these derived classes.
Could someone help show me the best way to do this?
EDIT:
Sorry, let me clarify my question a little more. I want to make sure of 2 things.
1) Name property exists in all derived classes
2) Name property is not null or empty
I basically want to force any class that derives from Item (and is not abstract) to have a value for Name.
It sounds like you are worried about initialising properties?
but I might forget to set the
base.Name in these derived classes.
One way the you can force the Name property to be set is to include this setter in your base class constructor like so:
public class MyBaseClass
{
private string _name;
public MyBaseClass(string name)
{
_name = name;
}
}
Then everything that derives from MyBaseClass must satisfy that constructor:
public class MyDerivedClass
{
public MyDerivedClass(string name) : base(name)
{
}
}
Then you can also make the property either:
abstract to ensure that it exists in each derived class with its own implementation
virtual to provide a base implementation and all it to be overridden.
I'm not going to venture whether the above is good design, but it would work to ensure that all derived classes have a valid name property when instantiated.
Another approach, as other answers suggest, is to implement a virtual property that throws an exception in its base implementation.
You only need to define Name in the base class, and do not need to specify it as abstract. It will still be available as a property in all derived classes.
public abstract class Item
{
public string Name { get; set; }
}
public abstract class Armor : Item
{ }
public class Helmet : Armor
{ }
If I do that the code looks a little cleaner but I might forget to set the base.Name in these derived classes.
Then the name of the object will just end up being something silly.
Better yet, have name start out as null. Then you'll get an exception if you forget to initialize the name but someone tries to use it, and you'll know you have to fix it.
Mike is right that if you just want to use the property "Name" on all derived objects, you don't need it to be marked abstract at all as it's inherited.
If you want to just force the fact that when Items are created, a name is definitely set, you could force it through hiding the zero-parameter constructor and exposing a constructor that accepts the name.
Take a look at this code:
public class Item
{
public string Name { get; set; }
public Item(string name)
{
this.Name = name;
}
protected Item() {}
}
public class Armor : Item
{
public Armor(string name) : base(name) {}
protected Armor() {}
}
public class Helmet : Armor
{
public Helmet(string name) : base(name) {}
protected Helmet() {}
}
The above definitions mean that:
Helmet myHelmet = new Helmet(); //will not build
Helmet myHelmet = new Helmet("Some Fancy Helmet Name"); //will build
Armor myArmor = new Armor (); //will not build
Armor myArmor = new Armor ("Some Fancy Armor Name"); //will build
Item myItem = new Item (); //will not build
Item myItem = new Item("Some Fancy Item Name"); //will build
This forces that any instance of the classes must define the name at time of creation. One possible solution anyway...
Would making Name a virtual ie. public virtual Name {get; set; } accessor be used in the Item class? Since Helment and Armor descend from the Item class. It would enforce that they must be overridden...
Hope this helps,
Best regards,
Tom.
so it depends what you want to do ...
making class abstract forces all the sub-classes to implement the class (and its abstract functions, etc.), but if you want a function to have a base functionality with the possibility to override the function then i'll suggest not making the class abstract and making the specific function virtual instead, thus when the virtual function is not being overwritten, and base function will be called.
and there's always options to create a "new" properties with the same name, but i don't think that's a good practice.
hope that helps.
i think you can still make the property virtual within a abstract class, thus that should solve your problem.
You can set the value to something specific in the base abstract class,
here an example :
public abstract class Item
{
public virtual string Name
{
get {return m_strName;}
set {m_strName = value;}
}
public abstract class Armor : Item
{
public override string Name { get; set; } // if you want to override it
}
public class Helmet : Armor
{
public override string Name { get; set; } // if you want to override it
}