DRY principle when working with multiple method signatures - c#

With the DRY principle in mind, how would you tackle almost identical methods (with different signatures) that work with an IEnumerable. I.e. one signature works with a specific type parameter. My question extends to the calling of private methods, and their multiple signatures.
I don't want to have two methods with identical logic - If something changes then I have to change both sets of logic. The calling of the private methods for example, how can I make the private method accept either type of IEnumerable
public class Person
{
public string Name {get; set;}
public string Age {get; set;}
}
public class SupremeBeing : Person
{
public string Power {get; set;}
}
public class Payroll
{
public void DoSomething(IEnumerable<Person> peopleIn)
{
// Do this with peopleIn
// Do that with peopleIn
// Call private method passing in peopleIn (which also has 2 signatures)
}
public void DoSomething(IEnumerable<SupremeBeing> peopleIn)
{
// Do this with peopleIn
// Do that with peopleIn
// Call private method passing in peopleIn (which also has 2 signatures)
}
}

It looks to me like what you want is more abstraction on the Payroll Class
public abstract class PayrollBase<T> where T : Person
{
public void DoSomething(IEnumerable<T> peopleIn)
{
// Do this with peopleIn
// Do that with peopleIn
this.InternalLogic(peopleIn);
}
protected virtual InternalLogic(IEnumerable<T> peopleIn)
{
// do something super special
}
}
You would then implement this for your specific types
public PersonPayroll : PayrollBase<Person>
{
protected override InternalLogic(IEnumerable<Person> peopleIn)
{ ... }
}
public SupremeBeingPayroll : PayrollBase<SupremeBeing>
{
protected override InternalLogic(IEnumerable<SupremeBeing> peopleIn)
{ ... }
}
You would then use some form of factory class to instantiate the right "Payroll" for the list of people you're dealing with.

The object oriented approach would be to make the classes handle their differences themselves. You can for example use virtual methods to have one implementation for each class.
When you can treat every object as a Person object regardless of the actual type, then you only need one set of methods to handle the payroll, and you wouldn't need to call it with separate lists for each class, you can put them all in the same list and call the method.
Example:
public class Person {
public string Name {get; set;}
public string Age {get; set;}
virtual public int Salary { get { return 1000 + Age * 10; } }
override public string ToString() {
return Name + "(" + Age + ")";
}
}
public class SupremeBeing : Person {
public string Power {get; set;}
override public int Salary { get { return 5000 + Age * 7; } }
override public string ToString() {
return Power + " " + Name;
}
}
public class Payroll {
public void DoSomething(IEnumerable<Person> peopleIn) {
foreach (Person p in peopleIn) {
Console.log("{0} earns {1}", p, p.Salary);
}
}
}

One option is to call the first method from the second:
public void DoSomething(IEnumerable<SupremeBeing> peopleIn)
{
this.DoSomething(peopleIn.Cast<Person>());
// do SupremeBeing specific stuff
}
Another option is to have a private method which does all the Person stuff.
public void DoSomething(IEnumerable<SupremeBeing> peopleIn)
{
this.DoSomethingWithPersons(peopleIn);
}
public void DoSomething(IEnumerable<Person> peopleIn)
{
this.DoSomethingWithPersons(peopleIn);
}
private void DoSomethingWithPersons(IEnumerable<Person> peopleIn)
{
// do stuff
}
Subtle differences between the two options without more information it's hard to know which would be better.

I don't understand your problem. You could create a generic method which does your generic stuff and then create a method which could be overridden for your special stuff.
Like:
class Something
{
protected virtual void DoSomethingSpecial<TYPE>(TYPE item)
{
}
public void DoSomethingy<TYPE>(IEnumerable<TYPE> items)
{
foreach(TYPE item in items)
{
// do whatever you have to do for every type
// do whatever you have to do in special
this.DoSomethingSpecial(item)
}
}
}
Code not tested just typed.
And then create one class for every special case. In these classes you just override DoSomethingSpecial for every type and you're done.

You could just have the Payroll class sort out the different types of Persons after it has run all the common operations and forward people to the appropriate extended methods.
interface IPerson {
string Name { get; set; }
string Age { get; set; }
}
public class Person : IPerson {
public string Name { get; set; }
public string Age { get; set; }
}
public class SupremeBeing : Person
{
public string Power { get; set; }
}
public class Payroll
{
public void DoSomething(IEnumerable<IPerson> peopleIn)
{
//..everyone does this and that
IEnumerable<Person> NormalPeople = peopleIn.OfType<Person>();
if (NormalPeople.Count() > 0) DoSomethingNormalSpecific(NormalPeople);
IEnumerable<SupremeBeing> SupremeBeings = peopleIn.OfType<SupremeBeing>();
if (SupremeBeings.Count() > 0) DoSomethingSupremeSpecific(SupremeBeings);
}
public void DoSomethingNormalSpecific(IEnumerable<Person> normalPeopleIn)
{
// just normal people
}
public void DoSomethingSupremeSpecific(IEnumerable<SupremeBeing> supremeBeingsIn)
{
// just Supreme Beings
}
}

Related

What is an appropriate way to change property accessors on sub classes whilst maintaining polymorphism?

I have a few classes that inherit from a base class for which I wish to change the implementation of a property and method. I also require the base class and all sub classes to be be polymorphic, so I can later create a collection of any type that implements a particular interface.
When i create instances of my classes that implement an interface, I want to use properties and methods on that class (implemented by the interface), not the base class.
This is my simplified implementation of the issue that provides the desired output but does have a code smell...
class Program
{
static void Main(string[] args)
{
IGrid one = new TextField();
IGrid two = new SelectList();
one.Click();
two.Click();
Console.WriteLine(one.Text);
Console.WriteLine(two.Text);
Console.ReadLine();
}
}
public interface IGrid {
string Text { get; set; }
void Click();
}
public class Control : IGrid {
public string Text {
get { return "Hello Control!"; }
set { }
}
public virtual void Click() {
Console.WriteLine("In the Control!");
}
}
public class SelectList : Control, IGrid {
public int Number { get; set; }
public new string Text {
get {
return "Hello Select!";
}
set { Number = int.Parse(value); }
}
public override void Click() {
Console.WriteLine("In the Select!");
}
}
public class TextField : Control, IGrid {
public int Number { get; set; }
public new string Text {
get {
return "Hello TextField!";
}
set { Number = int.Parse(value); }
}
public override void Click()
{
Console.WriteLine("In the TextField!");
}
}
This works but feels a little messy having an empty set in the Control class.
Is there a cleaner approach to this type of problem without compromising on specific property implementations on sub classes?
Many thanks,
Okay, so first thing is first, you should not be changing another property when you set a property (like you are doing to Number from Text). This is a huge code smell because it is a side effect. You should always deal directly with the properties that you intend to.
public class SelectList : Control, IGrid {
public int Number { get; set; }
public new string Text {
get {
return "Hello Select!";
}
// This is bad, someone after you may not know that this has a side effect
set { Number = int.Parse(value); }
}
}
Second, a property can be virtual just like a method, so marking your Text property as virtual and overridding in a derived class will make polymorphism work the way it is intended. "Hiding" via the new keyword would require you to cast your interface its specific class in order to get that classes implementation.
public class Control : IGrid
{
public virtual string Text
{
get { return "Hello Control!"; }
}
public virtual void Click()
{
Console.WriteLine("In the Control!");
}
}
public class SelectList : Control, IGrid
{
public int Number { get; set; }
public override string Text
{
get
{
return "Hello Select!";
}
}
public override void Click()
{
Console.WriteLine("In the Select!");
}
}
Third, you do not have to have a setter on the interface. You could just have a getter and only need to implement that.
public interface IGrid
{
string Text { get; }
void Click();
}
Finally, if you are ALWAYS going to override a method or property and NEVER going to create the base class directly (with a new) then you should consider using an abstract class if you have shared implementation (EG at least one method or property you do not change) or don't bother with the base class because you are not using any of the code anyways.
// Abstract class
public abstract class Control : IGrid
{
// Property that is not overridden but is shared
public int Number { get; set; }
public abstract string Text
{
get;
}
public abstract void Click();
}
public class SelectList : Control
{
// Don't need the Number property here, base class has it
public override string Text
{
get
{
return "Hello Select!";
}
}
public override void Click()
{
Console.WriteLine("In the Select!");
}
}
// Need everything in this class, but if it is all different anyways
// then base class is kind of a waste
public class TextField : IGrid
{
public int Number { get; set; }
public string Text
{
get
{
return "Hello TextField!";
}
}
public void Click()
{
Console.WriteLine("In the TextField!");
}
}

How to implement an interface to limit getting and setting properties of class

I am struggling with understanding C# interfaces. I understand that they allow for multiple inheritance. I'm trying to code for a scenario: Employees can view their own data, but not others. Managers can view and edit Employee information, if the Employee reports to that Manager.
So I start with an abstract class, since everyone is a User and takes vacation the same.
public abstract class User {
string _id;
string _firstName;
string _lastName;
double _salaryAmount;
double _bonusAmount;
int _vacationBalance;
public void TakeVacation(int hours) {
_vacationBalance -= hours;
}
//do I implement this here?
/*
public int SalaryAmount{ }
*/
}
Should I use an interface to define IEditable and IViewable?
Could I do something like this?
public interface IEditable {
double SalaryAmount { get; set; }
}
public class Employee : User, IEditable {
public double SalaryAmount {
get {
return base._salaryAmount;
}
set {
base._salaryAmount = value;
}
}
}
//Will I need a ReadOnlyEmployee or something?
I'm just not sure how to block a Manager from editing a User, or how to write an interface for this type of situation.
I'm not sure I'd say that Interfaces allow multiple inheritance (not in the true C++ form). An interface provides an abstraction which allows multiple implementations to behave consistently via a predefined set of methods/properties.
Often this is used as a general abstraction, for example say you want to get some data. You can create an Interface that surfaces a method that returns a Stream. Then based on the implementation of the object you can return the stream from a file or websocket or pipe, etc. without the consumer of the interface knowing/caring where it's coming from.
In your example you don't have to do anything in the User class, because it doesn't implement the IEditable interface, only the Employee class does.
Here's what I think you are looking for. This uses Explicit interface syntax (IEditable.Name) because the base method name and the interface name are the same but need to act differently.
public abstract class User {
public String Id { get; protected set; }
public String FirstName { get; protected set; }
public String LastName { get; protected set; }
// ...
public Double SalaryAmount { get; protected set; }
// ...
public Int32 VacationBalance { get; protected set; }
public void TakeVacation(int hours) {
VacationBalance -= hours;
}
}
public interface IEditable {
Double SalaryAmount { get; set; }
}
public class Employee: User, IEditable {
#region IEditable Members
double IEditable.SalaryAmount {
get { return base.SalaryAmount; }
set { base.SalaryAmount = value; }
}
#endregion
}
class Program {
static void Main(string[] args) {
var emp = new Employee();
emp.SalaryAmount = 3; // ERROR!
((IEditable) emp).SalaryAmount = 3; // GOOD!
}
}

Self-Referential Property array

I want to be able to loop through a Class Property that references its own properties. Why you may ask? Because it's easier to manage later on if I want to add more properties to that Class.
Let me explain more:
public interface IElementBox
{
string Filename { get; }
string FileDefinition { get; set; }
void ExtractFromFile(string stringData);
}
public abstract class Element
{
public Element(string stringData)
{
this.DefFromFile(stringData);
}
public string Name { get; set; }
protected abstract void DefFromFile(string stringData);
}
public class Solid : Element
{
public Solid(string stringData) : base(stringData) { }
public string SolidSpecificProperty { get; set; }
protected override void DefFromFile(string stringData)
{
// Assign SolidSpecificProperty from string
}
}
public class Liquid : Element
{
public Liquid(string stringData) : base(stringData) { }
public string LiquidSpecificProperty { get; set; }
protected override void DefFromFile(string stringData)
{
// Assign LiquidSpecificProperty from string
}
}
public class Gas : Element
{
public Gas(string stringData) : base(stringData) { }
public string GasSpecificProperty { get; set; }
protected override void DefFromFile(string stringData)
{
// Assign GasSpecificProperty from string
}
}
public abstract class ElementBox<T> : IElementBox where T : Element
{
public List<T> Elements { get; set; }
public List<T> GetElementsFromName(string name)
{
return this.Elements.FindAll(x => x.Name == name);
}
public abstract string Filename { get; }
public string FileDefinition { get; set; }
public abstract void ExtractFromFile(string filename);
}
public class SolidBox : ElementBox<Solid>
{
public override string Filename
{
get { return "Solid.txt"; }
}
public override void ExtractFromFile(string stringData)
{
this.Elements.Add(new Solid(stringData));
}
}
public class LiquidBox : ElementBox<Liquid>
{
public override string Filename
{
get { return "Liquid.txt"; }
}
public override void ExtractFromFile(string stringData)
{
this.Elements.Add(new Liquid(stringData));
}
}
public class GasBox : ElementBox<Gas>
{
public override string Filename
{
get { return "Gas.txt"; }
}
public override void ExtractFromFile(string stringData)
{
this.Elements.Add(new Gas(stringData));
}
}
public static class DataDefinition
{
public static SolidBox SolidBox { get; set; }
public static LiquidBox LiquidBox { get; set; }
public static GasBox GasBox { get; set; }
public static IElementBox[] ElementBoxes = new IElementBox[] { DataDefinition.SolidBox, DataDefinition.LiquidBox, DataDefinition.GasBox };
}
public static class Loader
{
public static void LoadInfo()
{
for (int elementBoxNb = 0; elementBoxNb < DataDefinition.ElementBoxes.Length; elementBoxNb++)
{
string dataFilepath = DataDefinition.ElementBoxes[elementBoxNb].Filename;
System.IO.StreamReader sr = System.IO.File.OpenText(dataFilepath);
DataDefinition.ElementBoxes[elementBoxNb].ExtractFromFile(sr.ReadToEnd());
}
}
}
The whole purpose of this structure is to be able to define all the object properties in a text file. So that all the SolidBox.Elements objects are dynamically assigned from that text file definition.
My questions are as follow:
Will the property array in DataDefinition be referenced by value. Which would mean that all my data assignation would get absorbed in the void?
If yes (or no..), is their a better way of doing the whole thing / What would be the best way to do it?
I've been working on that data structure for a while now I'm getting proud of what I could achieve. I would be sad if all that was done for nothing. Although, if one if you can provide me with a better/optimal way of doing the whole thing, I will be grateful and throw my code in my archive folder.
Also, keep in mind that this is an example of the data structure. It does not reflect exactly what my code looks like and is made so to ease comprehension and reading.
Don't hesitate to ask questions if more information is needed.
Deserialization (reading objects in from a persistent medium) has been solved a zillion different ways. Try using Data Contracts, like this answer demonstrates. You just need to add a few attributes to your properties to indicate what you want serialized and then it does just about all of the work for you.
This won't do what you want. The array will contain references to the objects referenced by the properties at the time it is initialised, which in this case will be null. If you assign something to the SolidBox property the associated element of the array won't change, and vice-versa.

Default object implementation

I want to implement default object pattern for my all classes in the inheritance tree. I am doing as shown below.
namespace test
{
public class Record
{
public int ID { get; set; }
}
public class StudentRecord : Record
{
public string StudentID { get; set; }
}
public class DriverRecord : Record
{
public string DLNumber { get; set; }
}
public class client
{
public static void Main()
{
StudentRecord st = StudentRecord.Default;
DriverRecord dr = DriverRecord.Default;
}
}
}
I want the default property or method to initialize all the class level properties to their defaults and I don’t want to repeat the implementation for each class. I just want to write on Record (base ) class . Can you provide some suggestions on this?
What you’re looking for is exactly what constructors are for. A constructor can call an inherited base constructor, so you need to do the base initialisation in only one place. Sometimes the basic functionality really does what you need :)
public class Record
{
public int ID { get; set; }
public Record()
{
// ... do general initialisation here ...
}
}
public class StudentRecord : Record
{
public string StudentID { get; set; }
public StudentRecord()
: base() // This calls the inherited Record constructor,
// so it does all the general initialisation
{
// ... do initialisations specific to StudentRecord here ...
}
}
public class client
{
public static void Main()
{
// This calls the constructor for StudentRecord, which
// in turn calls the constructor for Record.
StudentRecord st = new StudentRecord();
}
}
The Record class can only set the properties which are inherited by StudentRecord and DriverRecord. If you want to set class-specific properties to their default values you have to override the method (I would make a method) and do something like this (for StudentRecord ):
public void override Initialize()
{
base.Reset();
this.StudentId = 0;
}
HTH
You don't have any "class level properties", i.e. static properties, in your code sample. The properties you do have (the instance properties) are already initialized to their defaults -- 0 for integers, null for references, etc.
If you want to define your own defaults -- perhaps ID should default to -1 until you save, and the strings should default to "" -- then that's exactly what constructors are for:
public class Record
{
public Record() { ID = -1; }
public int ID { get; set; }
}
public class StudentRecord : Record
{
public StudentRecord() { StudentID = ""; }
public string StudentID { get; set; }
}
// etc.
If you want something different from either of those, you'll have to explain what you're looking for.
I think Null Object Pattern is what you need.

Extending a base class method

I am new to C# and am trying to understand basic concepts. Thank you in advance for your help. I have some sample classes below (typed in this window so there may be some errors)and have two questions:
Is it possible to Call a derived class method that executes the code in the base class method with the same name, then executes the code in the derived class method? Every derived class will need to perform the base class code for the RunCheck then do specialized code specific to its class. I could name RunCheck() something else in the base class and then call it when I call the RunCheck() of the derived class but then I have to remember to call it on the RunCheck() in the derived class.
In the Program.cs I want to output all fields with a blank value if it is on a field that is not in the derived class I pass in. What would I pass in?
Here is my code:
class baseCheck
{
public DateTime StartTime { get; set; }
public DateTime LastRun { get; set; }
public int Runs { get; set; }
//Others
public void RunCheck()
{
if (Started != null)
started = DateTime.Now;
LastRun = DateTime.Now;
Runs++;
}
}
class FileCheck : baseCheck
{
public string FileName { get; set; }
public void RunCheck()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
}
}
class DirectoryCheck : baseCheck
{
public string DirectoryName { get; set; }
public void RunCheck()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
}
}
//Program.cs
static void Main()
{
//Create derived class - either DirectoryCheck or FileCheck
//depending on what the user chooses.
if (Console.ReadLine()=="F")
{
FileCheck c = new FileCheck();
}
else
{
DirectoryCheck c = new DirectoryCheck();
}
PrintOutput(c);
}
private void PrintOut(What do I put here?)
{
Console.WriteLine("Started: {0}",f.StartTime)
Console.WriteLine("Directory: {0}", f.DirectoryName)
Console.WriteLine("File: {0}", f.FileName}
}
Just call base.RunCheck() in your DirectoryCheck class:
public class DirectoryCheck : baseCheck
{
public string DirectoryName { get; set; }
public void RunCheck()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
base.RunCheck();
Console.WriteLine("From DirectoryCheck");
}
}
Also with your current implementation you are hiding the base class RunCheck() method - you should really override it - this changes the method signature in the base class to
public virtual void RunCheck()
and in the derived classes to
public override void RunCheck()
I suspect what you really want though is something like the Non Virtual interface pattern (NVI) - Expose a protected virtual method in your base class, that child classes can override, but have a public method on the base class that is actually calling that method internally - this approach allows you to extend what you are doing before and after that call.
In your example this would look like this:
class BaseCheck
{
private DateTime Started { get; set; }
public DateTime StartTime { get; set; }
public DateTime LastRun { get; set; }
public int Runs { get; set; }
//Others
public void RunCheck()
{
if (Started != null)
Started = DateTime.Now;
LastRun = DateTime.Now;
Runs++;
CoreRun();
}
protected virtual void CoreRun()
{
}
}
public class DirectoryCheck : BaseCheck
{
public string DirectoryName { get; set; }
protected override void CoreRun()
{
//I want all the code in the base class to run plus
//any code I put here when calling this class method
Console.WriteLine("From DirectoryCheck");
}
}
In a derived class, you can call the method in the base class using:
public override void RunCheck()
{
base.RunCheck();
// Followed by the implementation of the derived class
}
As mentioned in the comments, the base method will need to be declared as virtual to allow overriding:
public virtual void RunCheck() { ... }
For your PrintOut() method, there is no magic way, but you could have it take the base class as a parameter, and then test for the type.
private void PrintOut(baseCheck f)
{
Console.WriteLine("Started: {0}", f.StartTime)
Console.WriteLine("Directory: {0}", f.DirectoryName)
if (check is FileCheck)
{
Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
}
}
Or you could use overloads:
private void PrintOut(baseCheck f)
{
Console.WriteLine("Started: {0}", f.StartTime)
Console.WriteLine("Directory: {0}", f.DirectoryName)
}
private void PrintOut(FileCheck f)
{
PrintOut((baseCheck)f);
Console.WriteLine("File: {0}", ((FileCheck)f).FileName}
}
Or you could have your PrintOut method part of your class (maybe even use the existing ToString() method) and override it as required.

Categories

Resources