Default value of fields in derived classes - c#

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.

Related

MongoDB C# Driver (2.7) and serialization issues

I'm currently having a strange issue with the latest mongodb c# driver (2.7), inheritance and serialization.
Here is a super simplified class hierarchy that I'm using:
public abstract class BaseClass
{
public Guid Id { get; private set; }
protected BaseClass(Guid id)
{
Id = id;
}
}
public class DerivedClass : BaseClass
{
public DerivedClass(Guid id) : base(id) {}
}
When I try to register the class for mongo serialization, I am getting an error:
var type = typeof(DerivedClass);
if (BsonClassMap.IsClassMapRegistered(type))
return;
var cm = new BsonClassMap(type);
cm.AutoMap();
BsonClassMap.RegisterClassMap(cm);
The error is:
The memberInfo argument must be for class DerivedClass, but was for class BaseClass.
Parameter name: memberInfo
Now, and this is where things start to get weird, when I tried to understand what was happening I made some changes to the BaseClass or the DerivedClass.
ANY of the two changes listed below will make the RegisterClassMap method work without errors...
change 1: adding a second, unused property on BaseClass
public abstract class BaseClass
{
public Guid Id { get; private set; }
public string Test { get; }
protected BaseClass(Guid id)
{
Id = id;
}
}
change 2: changing the Id property to have a non-private setter (any other works)
public abstract class BaseClass
{
public Guid Id { get; protected set; }
protected BaseClass(Guid id)
{
Id = id;
}
}
My question is... what is happening? While I may agree that for the serializer you should have an accessible setter for every property on the class that you want to map (in this case, DerivedClass), why the case #1 is actually not giving any error?

is it possible to set derived class default values without a constructor?

My goal is to make a static object that won't change, using a base class's member variables and abstract methods, as there will be multiple of these type of objects.
This is an example of what I want to do:
public abstract class BaseThing
{
public string Name { get; set; }
public string Description { get; set; }
public decimal Cost { get; set;}
public abstract void MethodThatDoesThings();
}
Then I want to have a derived object that has default values of those base variables, something like this (obviously doesn't work) :
public class DerivedThing : BaseThing
{
Name = "Name1";
Description = "Description1";
Cost = 1.00;
public override void MethodThatDoesThings()
{
//Actually does things
}
}
Is something like this possible without using a constructor? Not that I'm against using them, I'm just genuinely curious. Right now I feel as though my only option is to create many static classes that have the same properties.
No, you should implement a constructor for derived class to set default values. If you want to set default values, you can do it like this;
public class DerivedThing : BaseThing
{
public DerivedThing(string name = "Name", string description = "Description1", decimal cost = 1.0)
{
Name = name;
Description = description;
Cost = cost;
}
public override void MethodThatDoesThings()
{
}
}

Set default properties in base class from derived class

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") { ... }
}

c# inheriting from generic class

Let me describe the logic and then class structure. There are objects and all object must inherit from ConfigurationObjectBase. Each object must be owned by Manager and all Managers must be derived from ConfigurationObjectManagerBase. When a new instance of object created, one of the constructor must accept instance of Manager and that instance of Manager must add that instance of object into it's property called ChildObjects. Below is sample of classes. could you pls help to correct in below code acording above business rule? Thanks.
public class ConfigurationObjectBase<ObjectType>
{
public ConfigurationObjectBase(ConfigurationObjectManagerBase<ObjectType> ownerManager)
{
ownerManager.ChildObjects.Add(this);
}
}
public class ConfigurationObjectManagerBase<ObjectType>
{
public ConfigurationObjectManagerBase()
{
ChildObjects = new List<ObjectType>();
}
public List<ObjectType> ChildObjects { get; set; }
}
public class Catalog : ConfigurationObjectBase<Catalog>
{
public Catalog(CatalogManager ownerManager) : base(???)
{
}
}
public class CatalogManager : ConfigurationObjectManagerBase<CatalogManager>
{
public CatalogManager() : base()
{
}
}
There are two issues in your code:
CatalogManager should inherit from ConfigurationObjectManagerBase<Catalog>, not ConfigurationObjectManagerBase<CatalogManager>
ChildObjects should probably be a list of ConfigurationObjectBase<ObjectType>, rather than a list of ObjectType (otherwise you can't add a ConfigurationObjectBase<ObjectType> to it)
So the code should probably look like this:
public class ConfigurationObjectBase<ObjectType>
{
public ConfigurationObjectBase(ConfigurationObjectManagerBase<ObjectType> ownerManager)
{
ownerManager.ChildObjects.Add(this);
}
}
public class ConfigurationObjectManagerBase<ObjectType>
{
public ConfigurationObjectManagerBase()
{
ChildObjects = new List<ConfigurationObjectBase<ObjectType>>();
}
public List<ConfigurationObjectBase<ObjectType>> ChildObjects { get; set; }
}
public class Catalog : ConfigurationObjectBase<Catalog>
{
public Catalog(CatalogManager ownerManager) : base(ownerManager)
{
}
}
public class CatalogManager : ConfigurationObjectManagerBase<Catalog>
{
public CatalogManager()
{
}
}
Also, you don't need to call the default base class constructor (base()), it's done implicitly by the compiler.

How to make these n methods to a single generic method?

I have a base class like this:
public class BaseResponse
{
public string ErrorMessage { set;get;}
}
And some child classes which inherit from this:
public class Person:BaseResponse
{
public string FirstNAme { set;get;}
}
public class Phone:BaseResponse
{
public string SerialNumber { set;get;}
}
public class Car :BaseResponse
{
public string Year{ set;get;}
}
Now I want to set the ErrorMessage property of each instance of this class to a different value. Currently this is what I am doing:
public Phone GetPhoneError(Phone objPhone)
{
objPhone.ErrorMessage="Err msg related to Phone";
return objPhone;
}
public Person GetPersonError(Person objPerson )
{
objPerson .ErrorMessage="Err msg related to Person";
return objPerson ;
}
... another similar method for Car also
Is there any way I can make this method a generic format so that I don't need 3 separate methods for setting the error message?
public T GetError<T>(T obj) where T: BaseResponse
{
obj.ErrorMessage= string.Format("Err msg related to {0}", typeof(T).Name);
return obj;
}
I don't know if the error message is this generic thing or something custom. If so, then pass the message as an argument.
Why do you need a method for this? Is it because you have simplified the question?
So in your base class you should create a virtual method called SetError (your GetError but with the correct notation).
public abstract string GetErrorMessage(); //In Base Class so that why each implementation will set the correct error message
Then in your base class - also why do you need to return the same object that you are modifying?
public virtual void SetErrorMessage()
{
this.ErrorMessage = GetErrorMessage();
}
You should be able to have a generic method like so:
public object GetError(BaseResponse response)
{
response.ErrorMessage = "whatever";
return response;
}
Why not make property virtual and no need for set in that case ? :
public class BaseResponse
{
public virtual string ErrorMessage { get;}
}
public class Person:BaseResponse
{
.....
public override string ErrorMessage {get { return "Err msg related to Person";}}
}
public class Phone:BaseResponse
{
......
public override string ErrorMessage {get { return "Err msg related to Phone";}}
}
and so on for others....

Categories