Using Collection<Interface> is possible, but does it correct? - c#

The best practices are to program against the interface rather than the concrete class. I want to keep container of class that implements interface IPet. Does it correct? List<IPet> petList = new List<IPet>(); Or it's better to create an abstract class?
public interface IPet
{
string Name { get; set; }
void Introduce();
}
public class Parrot : IPet
{
public string Name { get; set; }
public Parrot(string name)
{
Name = name;
}
public void Introduce()
{
Console.WriteLine($"My name is {Name}. I am a parrot");
}
}
public class Cat : IPet
{
public string Name { get; set; }
public Cat(string name)
{
Name = name;
}
public void Introduce()
{
Console.WriteLine($"My name is {Name}. I am a cat");
}
}
PetShop petShop = new PetShop();
petShop.Add(new Cat("Garfield"));
petShop.Add(new Parrot("Kesha"));

Using interface in generics is the good choice!
Using abstract class force you to place any type in single chain of inheritance that can cause a problem with application evolution.
Besides, if you have a repeating behavoir you can create abstract class wich implements required interface, so you'll get advantages of both ways.

You can easily create an abstract class and put all repeating logic into it. Your classes look the same, only the Introduce() method is different, but you can use this.GetType().Name.ToLower() instead of "cat" and "parrot".
So, you can have the following:
public abstract class Pet : IPet
{
public string Name { get; set; }
protected Pet(string name)
{
Name = name;
}
public void Introduce()
{
Console.WriteLine($"My name is {Name}. I am a {this.GetType().Name.ToLower()}");
}
}
public class Cat : Pet
{
public Cat(string name)
: base(name)
{
}
}

Related

C# Resolving Base Class to Correct Repository Method Call Based on Implemented Type

In our current project, we have an abstract base user class that is implemented by multiple other user types. We have a comparison class that can compare any of these types and then needs to call a correct update api based on the implemented type. I am trying to avoid bringing an if(typeof(User)) logic tree into the code and was hoping to figure out some way to solve the issue with method overloading. Are there any design patterns that can help solve this issue with some type of interface that can be dependency injected? Here is a basic code example
using System;
using System.Collections.Generic;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
List<BaseUser> TestUsers = new List<BaseUser>();
TestUsers.Add(new UserA() { Email = "test1#test.com", Location = "New York, NY" });
TestUsers.Add(new UserB() { Email = "test2#test.com", State = "TN" });
foreach (var user in TestUsers)
{
//need to invoke the correct Print repo method based on the actual user type, possible interface?
}
Console.Read();
}
}
public abstract class BaseUser
{
public string Email { get; set; }
}
public class UserA : BaseUser
{
public string Location { get; set; }
}
public class UserB : BaseUser
{
public string State { get; set; }
}
public class UserARepo
{
void Print(UserA user)
{
Console.Write($"User A Saved {user.Email}, {user.Location}");
}
}
public class UserBRepo
{
void Print(UserB user)
{
Console.Write($"User B Saved {user.Email}, {user.State}");
}
}
}
If the Print methods only need the Email and Location/State properties of the objects, then change their signature to accept only these two strings.
I would add a common property to the abstract class, which returns the needed property in the User* classes:
namespace ConsoleApplication5
{
public abstract class BaseUser
{
public string Email { get; set; }
public string OtherLocation { get; set;}
}
public class UserA : BaseUser
{
public string Location { get; set; }
public string OtherLocation {
get
{
return this.Location;
}
set
{
this.Location = value;
}
}
}
public class UserB : BaseUser
{
public string State { get; set; }
public string OtherLocation {
get
{
return this.State;
}
set
{
this.State = value;
}
}
}
public class UserARepo
{
void Print(BaseUser user)
{
Console.Write($"User A Saved {user.Email}, {user.OtherLocation}");
}
}
public class UserBRepo
{
void Print(BaseUser user)
{
Console.Write($"User B Saved {user.Email}, {user.OtherLocation}");
}
}
}
Hopefully I'm understanding the problem correctly - but if each of those UserTypes needs an update API or Print Repo method, put them as abstract methods in the class:
public abstract class BaseUser
{
public string Email { get; set; }
public abstract void PrintRepo();
}
Basically, it's just a question of: what functionality is required of the subclasses if they want to implement your base class? They have to handle Update requests? Then put an abstract declaration in the abstract class that says, "Hey, if you inherit from me, you have to include an Update function."
Then your main function becomes something like:
foreach (var user in TestUsers)
{
user.PrintRepo();
}

Implementing interface properties in interfaces

I need to create a dll file which contains all the interfaces of the classes but doesn't contain any class.
Because I use these interfaces for a lot of classes it's must be like that:
public interface IClassA
{
string Word { get; }
}
public interface ITest<TClassA> where TClassA : IClassA
{
TClassA A { get; }
}
Example of two classes that implements these interfaces the way I want:
public class ClassA : IClassA
{
public string Word
{
get;
private set;
}
public string Sentence
{
get;
private set;
}
public ClassA(string word, string sentence)
{
this.Word = word;
this.Sentence = sentence;
}
}
public class Test : ITest<ClassA>
{
public ClassA A
{
get;
private set;
}
public Test(ClassA a)
{
this.A = a;
}
}
And I want to do something like that in the main program:
public static void Main(string[] args)
{
ClassA a = new ClassA("hey", "hey world!");
Test t = new Test(a);
Print((ITest<IClassA>)t);
}
public static void Print(ITest<IClassA> t)
{
Console.WriteLine(t.A.Word);
}
But this casting: (ITest<IClassA>)t makes a run time error.
How can I solve it?
thanks!
You should declare Test as
public class Test : ITest<IClassA>
instead of ITest<ClassA>.
Or declare ITest<TClassA> to be covariant on TClassA:
public interface ITest<out TClassA> where TClassA : IClassA
The Test-class implements the concrete ClassA (public class Test : ITest<ClassA>).
So you're trying to cast an ITest<ClassA> to ITest<IClassA> which obviously fails.
If you let the Test-class implement IClassA, the cast works:
public class Test : ITest<IClassA>
{
public IClassA A
{
get; private set;
}
public Test(IClassA a)
{
this.A = a;
}
}

Getting properties from generic type used in abstract superclass without using interfaces?

Is there any nice, elegant way to get properties from generic type used in abstract superclass without using interfaces?
Here's an example:
public abstract class CoolBase<T>
where T : class
{
private IEnumerable<T> somEnumerable;
public void GetPersonProperties()
{
var name = somEnumerable.First().Name; //this doesn't work
}
}
public class CoolA : CoolBase<Person>
{
}
public class Person
{
public string Name { get; set; }
public string Region { get; set; }
}
}
The goal of using generic classes is type-flexibility -
therefore it makes no sence to declare a method in a generic class which
uses Person-specific methods.
You should implement such detailed methods in the concrete implementations of
your abstract, generic class (here CoolA).
Maybe it is helpful for you to declare an abstract method getProperties()
int the generic, abstract class, wich can be implemented in CoolA via using
Person-specific code.
public abstract class CoolBase<T>
where T : class
{
private IEnumerable<T> somEnumerable;
public abstract void getProperties();
}
public class CoolA : CoolBase<Person>
{
public override void getProperties()
{
//should work, somEnumberable is made of Persons here
var name = somEnumerable.First().Name;
}
}
It makes no sense to put GetPersonProperties in CoolBase. CoolBase is generic, so should not have a class-specific functionality within it.
You could create a abstract method in CoolBase and implement it in your derived type:
public abstract class CoolBase<T> where T : class
{
protected IEnumerable<T> somEnumerable;
public abstract void GetProperties();
}
public class CoolA : CoolBase<Person>
{
public override void GetProperties()
{
var name = somEnumerable.First().Name;
}
}
public class Person
{
public string Name { get; set; }
public string Region { get; set; }
}
Alternatively, you could you reflection to get at the properties of T at runtime:
public abstract class CoolBase<T> where T : class
{
private IEnumerable<T> somEnumerable;
public void GetProperties()
{
foreach (var prop in typeof (T).GetProperties())
{
// do something with each property
}
}
}

Identical classes with different names

I want to be a little be more descriptive in my class names. I have three identical classes that look like this:
public class Dog
{
public string name;
public int id;
public Dog(){}
public Dog(DataRow dr)
{
name = dr["Name"];
id = dr["Id"];
}
}
public class Cat
{
public string name;
public int id;
public Cat(){}
public Cat(DataRow dr)
{
name = dr["Name"];
id = dr["Id"];
}
}
public class Horse
{
public string name;
public int horseId;
public Horse(){}
public Horse(DataRow dr)
{
name = dr["Name"];
horseId= dr["horseId"];
}
}
How do I avoid code duplication by using a base class? What are the best practicies? pplease note that horse has a property called HorseId instead of Id. Thanks.
Use inheritance.
public class Animal
{
public string name;
public int id;
public Animal() {}
public Animal(DataRow dr)
{
name = (string)dr["Name"];
id = (int)dr["Id"];
}
}
// unfortunately, constructors aren't inherited automatically in C#.
public class Cat : Animal
{
public Cat() : base() {}
public Cat(DataRow dr) : base(dr) {}
}
public class Dog : Animal
{
public Dog() : base() {}
public Dog(DataRow dr) : base(dr) {}
}
public class Horse: Animal
{
public int horseId { get { return id; } set { id = value; } }
public Horse() : base() {}
public Horse(DataRow dr) : base(dr) {}
}
EDIT: as Blorgbeard says, you can make Animal an abstract class if you want - that will prevent instantiation (new Animal() will be illegal; client code will have to pick a specific subclass).
I would make an interface called IAnimal that has properties name and id and have all 3 classes above implement this interface. Note is is slightly different than what you have here, as what you have here shows public variables, not public properties. If you want to maintain variables, then I would use a base class Animal with public variables name and id and convert horseId to a property that, interally, gets and sets the base id property like this public int horseId { get { return base.id; } set { base.id = value; } }
I'd do something like this - an abstract base class.
public abstract class Animal {
public string name;
public int id;
protected Animal() {}
protected Animal(DataRow dr) {
name = (string)dr["Name"];
id = (int)dr["Id"];
}
}
public class Cat : Animal {
public Cat() : base() {}
public Cat(DataRow dr) : base(dr) {}
}
Then just add a property to Horse (still leaving id as well)
public class Horse : Animal {
public int horseid { get { return id; } set { id = value; } }
public Horse() : base() {}
public Horse(DataRow dr) : base(dr) {}
}
This method doesn't allow you remove/hide id in the Horse class, so you will have both id and horseid, but they will use the same variable underneath.
As far as some good examples on object oriented design, I'd recommend two books.
The Object Oriented Thought Process
Agile Principles, Patterns and Practices in C# by Robert C. Martin. This book is just awesome at explaining great principles of OOP.

IPersistable Interface - Any trick or hack to change field name

For a class that can be saved in a persistence medium i am creating Interface called IPersistable which is designed to provide a persistenceId.
public interface IPersistable
{
private readonly string persistenceId;
}
Certainly i can't do the above since Interfaces do not allow fields. If it did i would have done below to accomplish it
Public Class Customer
{
private readonly string persistenceId;
Public string UserId
{
get{return persistenceId};
}
Public Customer(string customerId)
{
persistenceId = customerId;
}
}
I already am inheriting a class hence not possible to do multiple inheritance. I could use composition but Interface seems right thing here. Show me a neat hack to do the above instead of adding a property to each class that needs to be persisted.
Question
If possible, can a class that Interfaces with IPersistable change the name of the property( if persistenceId is a property), to something meaningful ?
An interface won't help you if you want to be able to persist existing types such as int or string. Maybe instead of an interface you could use a wrapping class? Something like:
class Persistable<T>
{
public Persistable<T>(string PersistanceId, T Data)
public readonly string PersistanceId;
public readonly T Data;
}
What's wrong with?
public interface IPersistable
{
String PersistenceId { get; }
}
Public Class Customer : IPersistable
{
public string PersistenceId { get; private set; }
public string UserId {
get { return PersistenceId; }
}
.
.
.
}
Try something like this:
public interface IPersistable<TType>
{
TType PersistenceId { get; }
}
public abstract PersistableEntity<TType> : IPersistable<TType>
{
private TType persistenceId;
public TType PersistenceId
{
get { return persistenceId; }
}
public PersistableEntity(TType persistenceId)
{
this.persistenceId = persistenceId;
}
}
public class Customer : PersistableEntity<string>
{
public Customer(string persistenceId)
: base(persistenceId)
{
}
}

Categories

Resources