I’m trying to build a class which will initalise its self either by passing in a reference to a record in a database (with the intention that a query will be run against the database and the returned values for the objects properties will be set therein), or by specifying the values “by hand” – this no database call is required.
I’ve looked at a couple textbooks to discover the “Best-practice” for this functionality and sadly I’ve come up short.
I’ve written a couple sample console apps reflecting what I believe to be the two most probable solutions, but I’ve no Idea which is the best to implement properly?
Sample App #1 uses what most books tell me is the “preferred” way but most examples given alongside those claims do not really fit the context of my situation. I’m worried in here that the flow is not as readable as App #2.
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester() : this(0) { }
public OverloadedClassTester (int _ID) : this (_ID, "", 0)
{
this.age = 14; // Pretend that this was sourced from a database
this.Name = "Steve"; // Pretend that this was sourced from a database
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
This Sample (App #2) “appears” more readable – in that I think it’s easier to see the flow of operation. However it does appear efficient in terms of characters saved :p. Also, is it not dangerous that it calls a method of the object before it’s fully initialised, or is this not a concern?
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester()
{
initialise(0, "", 21); // use defaults.
}
public OverloadedClassTester (int _ID)
{
var age = 14; // Pretend that this was sourced from a database (from _ID)
var Name = "Steve"; // Pretend that this was sourced from a database (from _ID)
initialise(_ID, Name, age);
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
initialise(_ID, _Name, _age);
}
public void initialise(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
What is the “correct” way to solve this problem, and why?
Thanks,
I would definitely chain the constructors, so that only one of them does the “real work”. That means you only have to do the real work in one place, so if that work changes (e.g. you need to call some validation method at the end of the constructor) you only have one place where you need to change the code.
Making “simple” overloads call overloads with more parameters is a pretty common pattern IME. I find it more readable than the second version, because you can easily tell that calling one overload is going to be the same as calling the “bigger” one using the default values. With the second version, you have to compare the bodies of the constructors.
I try not to have more than one constructor which chains directly to the base class wherever possible – unless it’s chaining to a different base class constructor, of course (as is typical with exceptions).