Creating a virtual generic method in C# - c#

I have some base classes like this:
public class AbstractData
{
public int ID { get; set; }
}
public class Person: AbstractData
{
public string Name { get; set; }
}
public class AbstractManager<T> where T: AbstractData
{
public virtual List<T> GetAll()
{
}
public virtual T GetOne(int id)
{
}
}
public class PersonManager: AbstractManager<Person>
{
public override List<Person> GetAll()
{
//...
}
public override Person GetOne(int id)
{
//...
}
}
Now, I have a Windows Forms base class, like this:
public class BaseForm: Form
{
public virtual AbstractManager<T> GetManager<T>() where T: AbstractData
{
return null;
}
}
and a derived form:
public class PersonForm: BaseForm
{
public override AbstractManager<T> GetManager<T>()
{
return new PersonManager();
}
}
The problem is, I keep getting compile errors on the PersonForm class:
Cannot implicitly convert type 'PersonManager' to 'AbstractManager<T>'
Is there a way in which I can create this virtual method and have every class derived from BaseForm return the concrete representation of the AbstractManager?
If I get rid of the generic on the AbstractManager class then I compile OK (with a few code changes), but then the GetAll method can't return a List<T>. It would have to return a List<AbstractData> instead, which causes issues in converting from List<Person> to List<AbstractData>.
Any help would be appreciated.

First off all, please never do this:
class C<T>
{
void M<T>(T t) { }
}
Now we have two things named T both in scope and they are different. This is legal but extremely confusing. Choose better names for your type parameters.
Let's simplify your example:
class FruitBasket<T> where T : Fruit { }
class AppleBasket : FruitBasket<Apple> { }
class C
{
public static FruitBasket<T> GetBasket<T>() where T: Fruit
{
return new AppleBasket();
}
}
Now do you see why this is wrong? What if someone calls C.GetBasket<Orange>() and you hand them a basket of apples?
Any help would be appreciated.
What's step one of getting out of a hole? STOP DIGGING.
You have Genericity Happiness Disease, which is common to C# programmers who are discovering the power of the generic type system and then want to use it for everything whether that makes sense or not. Stop trying to capture all the relationships in your business process in the generic type system; that's not what it was designed for.
The test is: can you say "an apple basket is a basket of apples, where apples are a kind of fruit" and have someone who is not a programmer agree with you? Yes. Can you say "a person manager is an abstract manager of persons where person is a kind of abstract data" and have someone who is not a programmer agree with you? No. Then you are not successfully modeling the business domain in the type system. Start over, avoid generics, and try to come up with relationships between types that make sense.

By declaring
public virtual AbstractManager<T> GetManager<T>() where T: AbstractData
in BaseForm, you're promising that every class derived from BaseForm supports GetManager for any type T. For example, if you had another AbstractData subclass named Invoice, then you could write
personForm.GetManager<Invoice>()
and PersonForm would be expected to return an InvoiceManager.
If you want every class derived from BaseForm to support GetManager for only one type T, then move the T type parameter from GetManager to BaseForm:
public class BaseForm<T>: Form where T: AbstractData
{
public virtual AbstractManager<T> GetManager()
{
return null;
}
}
public class PersonForm: BaseForm<Person>
{
public override AbstractManager<Person> GetManager()
{
return new PersonManager();
}
}
UPDATE: Chad Henderson points out that the Windows Forms designer can't handle generic base classes. If that's a problem for you, then you could try an alternate approach:
public interface IForm<T> where T: AbstractData
{
AbstractManager<T> GetManager();
}
public class BaseForm: Form
{
// ... base functionality that doesn't depend on T ...
}
public class PersonForm: BaseForm, IForm<Person>
{
public AbstractManager<Person> GetManager()
{
return new PersonManager();
}
}

Related

How to avoid casting derived types - Liskov's Principle violation

I want to avoid using casting base class type to derived class type I can do this successfully If I want to access generic functionality but if I want specialised functionality I cant access this without casting
I have written code to demonstrate what I've already tried.
public abstract class Animal : IAnimal
{
public void Move()
{
}
}
public interface IAnimal
{
void Move();
}
public interface IDog:IAnimal
{
void bark();
}
public class Dog : IDog
{
public void Move()
{
}
public void bark()
{
}
}
static void Main(string[] args)
{
Animal animal = null;
IDog dog = animal as IDog;
dog.bark(); // can access specialized method
IAnimal puppy = new Dog();
puppy.Move(); // can only access generic functions
}
How can I re-design classes to access "bark" method without casting?
Short answer: You cannot and you shouldn't be able.
What you could do instead, is probably implement a MakeNoise() method in IAnimal interface because you'd expect animals in general to make noises.
However, if you insist on keeping Bark() on IDog, you wouldn't expect an IDuck to be able to access it - it should have a Quack() method. Neither will be available from objects downcasted to IAnimal because how can you guess whether it's a Duck or a Dog?
I'll post bit more "real life" example of why you might need inheritance in programming, because example you've provided is sort-of "book example" and thus it is obscure and vague as well.
using System.Collections.Generic;
namespace ConsoleApp1
{
public static class DocumentHandling
{
public static List<IAccountable> Documents;
public static dynamic InternalService { get; set; }
public static dynamic IRS { get; set; }
public static void HandleDocuments()
{
foreach (var document in Documents)
{
document.Account();
}
}
}
public interface IAccountable
{
void Account();
}
public abstract class Document
{
public int DatabaseId { get; set; }
public string Title { get; set; }
}
public abstract class DocumentWithPositions : Document
{
public int[] PositionsIds { get; set; }
}
public class Invoice : DocumentWithPositions, IAccountable
{
public void Account()
{
var positions = DocumentHandling.InternalService.PreparePositions(this.PositionsIds);
DocumentHandling.IRS.RegisterInvoice(positions);
}
}
public class Receipt : DocumentWithPositions, IAccountable
{
public void Account()
{
Invoice invoice = DocumentHandling.InternalService.ConvertToReceipt(this);
invoice.Account();
}
}
}
See how I can stuff both Invoice and Receipt documents in single List (because they're downcasted to IAccountable)? Now I can account them all at once, even though their concrete implementations handle accounting process differently.
Let's takle the Liskov Substitution Principle first and then talk about OOP and inheritance.
First, lets talk about Abstract Data Types. In her paper she uses the concept of objects from types.
An Abstact Data Type (ADT) is a description of a type with all it's operations and behaviors. All clients of an ADT should know what to expect when using it.
Here's an example:
Let's define a Stack as an ADT
Operations: push, pop, topElement, size, isEmpty
Behaviors:
push : always adds an element to the top of the stack!
size : return the number of elements in the stack
pop : removes and element from the top of the stack. error if the stack is empty
topElement : return the top element in the stack. error if the stack is empty
isEmpty : return true is the stack is empty, false otherwise
At this point we desribed what is a Stack in terms of it's operations and how it should behave. We are not talking about clases here nor concrete implementations. This makes is an Abstract Data Type.
Now lets make a type hierarchy. In C# both interfaces and classes are types. They are different as interfaces define only operations, so in a sense they are a contract. They define the operations of an ADT. Usually people do assume that only classes that inherit from one another define a type hierarchy. It's true that classes that inherit from one another are called Superclass or Baseclass and a Subclass, but from the point of view of Types we do have Supertype and Subtype for both interfaces and classes as they both define types.
NOTE: For simplicity i'll skip error checking in the implementations of the methods
// interfaces are types. they define a contract so we can say that
// they define the operations of an ADT
public interface IStack<T> {
T Top();
int Size();
void Push(T element);
void Pop();
bool IsEmpty();
}
// the correct term here for C# whould be 'implements interface' but from
// point of view of ADTs and *Types* ListBasedStack is a *Subtype*
public class ListBasedStack<T> : IStack<T> {
private List<T> mElements;
public int Size() { return mElements.Count; }
public T Top() { mElements(mElements.Count - 1); }
public void Push(T element) { mElements.Add(element); }
public void Pop() { mElements.Remove(mElements.Count - 1); }
public bool IsEmpty() { return mElements.Count > 0; }
}
public class SetBasedStack<T> : IStack<T> {
private Set<T> mElements;
public int Size() { return mElements.Count; }
public T Top() { mElements.Last(); }
public void Push(T element) { mElements.Add(element); }
public void Pop() { mElements.RemoveLast(); }
public bool IsEmpty() { return mElements.Count > 0; }
}
Notice that we have two Subtypes of the same ADT. Now lets consider a test case.
public class Tests {
public void TestListBasedStackPush() {
EnsureUniqueElementsArePushesToAStack(new ListBasedStack<int>());
}
public void TestSetBasedStackPush() {
EnsureUniqueElementsArePushesToAStack(new SetBasedStack<int>());
}
public void EnsureUniqueElementsArePushesToAStack(IStack<int> stack) {
stack.Push(1);
stack.Push(1);
Assert.IsTrue(stack.Size() == 2);
}
}
And the results are:
TestListBasedStackPush: Pass
TestSetBasedStackPush: FAIL!
SetBasedStack violates the rules for push: always adds an element to the top of the stack! as a set can contain only unique elements and the second stack.Push(1) wont add new element to the stack.
This is a violation of LSP.
Now about examples and type hierarchies like IAnimal and Dog. When you are in the right abstaction level a type should behave like it's suposed to. If you do need a Dog, use a Dog. If you do need an IAnimal, use IAnimal.
How do you access Bark if you have IAnimal? You DON'T!!. You are at the wrong level of abstraction. If you do need a Dog, use a Dog. Cast if you have to.
public class Veterenerian {
public void ClipDogNails(IAnimal animal) { } // NO!
public void ClipDogNails(Dog dog) { } // YES!
}
private Veterenerian mOnDutyVeterenerian;
private List<IAnimal> mAnimals;
public ClipAllDogsNails() {
// Yes
foreach(var dog in mAnimals.OffType<Dog>()) {
mOnDutyVeterenerian.ClipDogNails(dog);
}
// NO
foreach(var animal in mAnimals) {
mOnDutyVeterenerian.ClipDogNails(animal);
}
}
Do you need to cast? Sometimes yes. If it better to not do it? Yes, most of the time.
How do you solve the above problem? You can make the Dog clip it's own nails. Are you doing to add method ClipNails to IAnimal and make only animals with nails implement this and leave other animal subclasses leave this method empty? NO! Because it doesn't make sense in the level of abstraction of IAnimal and it also violates LSP. Also if you do this you can call animal.ClipNails() and this will be fine, but if you do have a schedule that says that dogs should clip nails on Friday other animals Monday your stuck again as you can make all animals clip their nails, not only dogs.
Sometimes an object of one Type is to be used by objects from another Type. Some operations doesn't make sense in a type. This example illustates how a Dog cannot clip it's nails. It should be done by a Veterenerial.
Yet we do need to work on the IAnimal level of abstraction. All things in a Veterenerian Clinic are animals. But sometimes some operations need to be performed on specific type of animal, a Dog in this case, so we do need to filter the animals by their Type.
But that's a completely different problem from the above example with Stack.
Here's an example on when casting should not be used and the client code should not case about the concrete implementation:
public abstract class Serializer {
public abstract byte[] Serialize(object o);
}
public class JSONSerializer : Serializer {
public override byte[] Serialize(object o) { ... }
}
public class BinarySerializer : Serializer {
public override byte[] Serialize(object o) { ... }
}
public void DoSomeSerialization(Serializer serializer, Event e) {
EventStore.Store(serializer.Serialize(e));
}
DoSomeSerialization method should not care about the serializer that is passed to it. You can pass any Serializer that adheres to the Serializer spec, it should work. That's the point of having an abstraction with multiple implemenations. DoSomeSerialization works on the level of Serializer. We can define the Serializer as an ADT. All classes that are derive from Serializer should adhere to the specification of the ADT and the system works just fine. No casting here, no need to do casting here as the problem is different.

Generic objects in c#

i have a litte problem and i need some help :)
For example i have a simle abstract class
public abstract class BaseDefinition
{
public int Id { get;set; }
public string Name { get;set; }
}
and other base class
public abstract class BaseParentClass
{
public string Name { get;set; }
public string Schema { get;set; }
}
and first generic abstract class
public abstrac class BaseParentClass<T> :
BaseParentClass where T : BaseDefinition
{
public IList<T> Objects {get;set;}
}
and first implementations
public class ClassADefintion : BaseDefinition
{
public bool IsChanged {get;set;}
}
public class ClassAObject : BaseParentClass<ClassADefinition>
{
public bool OtherField {get;set;}
}
public class ClassBDefintion : BaseDefinition
{
public bool IsBBBChanged {get;set;}
}
public class ClassBObject : BaseParentClass<ClassBDefinition>
{
public bool OtherBBBBField {get;set;}
}
Sorry for class name, but I can't create anything better (it's only example)
As We see, now is all OK :).
I have some methods who returns a IEnumerable of generic implementation
IEnumerable<ClassBObject> ClassBObjectCollection;
IEnumerable<ClassAObject> ClassAObjectCollection;
Now i must create a method, who can take a generic objects in IEnumerable
public void DoWork(IEnumerable<BaseParentClass<BaseDefinition>> objects)
{
foreach(var baseObj in objects)
{
foreach(var baseDef in baseObj.Objects)
{
// do some work
}
}
}
How i remember BaseObject<BaseDefinition> != ClassAObject, but compiler doesn't put on screen any errors. I remember in .NET in generic interface We can use IN and OUT T, so i try make this
public interface IBaseParentClass<out T> where T : BaseDefinition
{
IList<T> Objects {get;set;}
}
Yup, You can't make a List of <out T>. Somebody have any idea for this problem ?
I can get this fields values by reflection, but i have abstract class and interface so i think is a better way.
I don't have a compiler at hand, but I think it should be possible to rewrite DoWork as such:
public void DoWork<T>(IEnumerable<BaseObject<T>> objects)
where T : BaseDefinition
{
foreach(var baseObj in objects)
{
foreach(var baseDef in baseObj.Objects)
{
// do some work
}
}
}
I am not sure whether the compiler will be able to infer T for you, try it out.
Another possibility may be that if you enumerate those objects anyway, to make Objects of Type IEnumerable(Of T).

What is the best way to design this class hierarchy?

I have a database table which contains an ID column and a Name column. I am tasked with designing a program that accepts one of the IDs as an argument to Main().
Bold is edit 2
I need to use that ID which must exist in the database, to correspond to some code to run. Each row in the table corresponds to slightly different code, but a lot of them share a lot of code. I need a design that will minimize code duplication.
So far what I've developed is an abstract base class that has an abstract Int32 field ID to enforce derived classes having their corresponding ID in the database. That way I can reflect over the derived classes to find the one whose ID matches the Main() argument and instantiate that class. Then I just call the virtual methods from Main() which runs the most derived code that has been defined.
public abstract class Base {
public abstract Int32 Id { get; }
public void Foo() {
// Do something
}
}
public class Derived {
public override Int32 Id { get { return 42; } }
public void Foo() {
// Do something more specific
}
}
Does anyone have any better ideas how to achieve what I want? I like the idea of keeping the ID right in the class definition, but I'm open to changing that if it makes sense.
Thanks!
EDIT:
One thing I don't like about this is that I have to reflect over each derived type and instantiate that type to check the ID. Does anyone have a better idea on how to do that?
Instead of using a property to define the ID of the class, use a custom attribute. That way, you don't have to instantiate the object to check what its ID is.
When your program runs, it can scan the assembly for all classes with that attribute tag, and find the one with the matching ID, instantiate that class, and then run it's Foo method. If you perform this kind of lookup multiple times per application run, you could instatiate all the classes with your custom attribute and then put them into a Dictionary to provide quick lookups by ID.
Your code might look something like this:
[AttributeUsage(AttributeTargets.Class)]
public class CommandAttribute {
public CommandAttribute(int id) {
ID = id;
}
public int ID { get; private set; }
}
public abstract class Command {
public abstract void Execute();
}
[Command(2)]
public class MyCommand : Command {
public override void Execute() {
//Do something useful
}
}
The other advantage of using a custom attribute is that you have to explicitly tag everything that is a candidate for being instantiated and executed by ID, rather than assuming than anything derived from your base class is a candidate. If you are sharing code between the classes, you might want to make a common base class for them that derives from your base class, but should not be instantiated or executed on its own.
One thing I don't understand is, what is the point of the "Name" field if the class you want to run is identified by the ID? If you can decide what the name of each ID is, then you could use the name field as the fully qualified type name of the class you want to execute, which then avoid having to scan through all the types in your assembly (or application domain, depending upon the scope of your search). That setup is a bit more prone to typos, however.
It sounds like you need to implement a factory pattern.
I would define an interface:
public interface IWidget
{
void Foo();
}
Then the base class:
public abstract class WidgetBase : IWidget
{
public void Foo()
{
this.Bar()
}
protected virtual void Bar()
{
// Base implementation
}
}
The factory:
public static WidgetFactory
{
public static IWidget Create(int id)
{
// Get class name from id, probably use the name in your database.
// Get Type from class name
// Get constructor for Type
// Create instance using constructor and return it.
}
}
A derived class:
public class DerivedWidget : WidgetBase
{
protected override void Bar()
{
// call base implementation
base.Bar();
// derived implementation
}
}
In your main:
public void Main(int id)
{
var widget = WidgetBase.Create(id);
widget.Foo();
}
I like #Xint0's idea of using a Factory for this kind of task, but I thought I'd still contribute another answer.
A better way to implement your original design would be to pass the ID to the base constructor as follows:
public abstract class Base {
public Int32 Id { get; private set; }
protected Base(Int32 id) {
this.Id = id;
}
public void Foo() {
// Do something
}
}
public class Derived : Base {
public Derived : base(42) {}
public void Foo() {
// Do something more specific
}
}

c# - cast generic class to its base non-generic class

I have following classes:
public abstract class CustomerBase
{
public long CustomerNumber { get; set; }
public string Name { get; set; }
}
public abstract class CustomerWithChildern<T> : CustomerBase
where T: CustomerBase
{
public IList<T> Childern { get; private set; }
public CustomerWithChildern()
{
Childern = new List<T>();
}
}
public class SalesOffice : CustomerWithChildern<NationalNegotiation>
{
}
The SalesOffice is just one of few classes which represent different levels of customer hierarchy. Now I need to walk through this hierarchy from some point (CustomerBase). I can't figure out how to implement without using reflection. I'd like to implement something like:
public void WalkHierarchy(CustomerBase start)
{
Print(start.CustomerNumber);
if (start is CustomerWithChildern<>)
{
foreach(ch in start.Childern)
{
WalkHierarchy(ch);
}
}
}
Is there any chance I could get something like this working?
The solution based on suggested has-childern interface I implemented:
public interface ICustomerWithChildern
{
IEnumerable ChildernEnum { get; }
}
public abstract class CustomerWithChildern<T> : CustomerBase, ICustomerWithChildern
where T: CustomerBase
{
public IEnumerable ChildernEnum { get { return Childern; } }
public IList<T> Childern { get; private set; }
public CustomerWithChildern()
{
Childern = new List<T>();
}
}
public void WalkHierarchy(CustomerBase start)
{
var x = start.CustomerNumber;
var c = start as ICustomerWithChildern;
if (c != null)
{
foreach(var ch in c.ChildernEnum)
{
WalkHierarchy((CustomerBase)ch);
}
}
}
You could move the WalkHierarchy method to the base class and make it virtual. The base class implementation would only process the current node. For the CustomerWithChildern<T> class, the override would do an actual walk.
Try this:
if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>))
I believe that you want to make the lookup for the determination of doing to the walk an interface.
So maybe add an "IWalkable" interface that exposes the information needed to do the walk, then you can create your method checking to see if the passed object implements the interface.
"Is" and "As" only work on fully qualified generic types.
See this MSDN discussion for details including workarounds.
The most common workaround I've seen is to add an interface to the mix that your CustomerWithChildren could implement, and check for that interface.
I think everyone hits this "issue" when first working with generic classes.
Your first problem is hinted at in your question phrasing: an open generic type is NOT the base class to a closed one. There is no OO relationship here, at all. The real base class is CustomerBase. An "open" generic type is like a half-completed class; specifying type arguments "closes" it, making it complete.
While you can do:
Type t = typeof(CustomerWithChildern<>)
the condition
typeof(CustomerWithChildern<>).IsAssignableFrom(CustomerWithChildern<Foo>)
will always be False.
-Oisin
Explicitly with that method, no. However you can achieve the same functionality with an interface. In fact, you could just have your generic class implement IEnumerable. It's also worth noting that your class should also have "where T : CustomerBase" in order to ensure type safety.

What is the best way to inherit an array that needs to store subclass specific data?

I'm trying to set up an inheritance hierarchy similar to the following:
abstract class Vehicle
{
public string Name;
public List<Axle> Axles;
}
class Motorcycle : Vehicle
{
}
class Car : Vehicle
{
}
abstract class Axle
{
public int Length;
public void Turn(int numTurns) { ... }
}
class MotorcycleAxle : Axle
{
public bool WheelAttached;
}
class CarAxle : Axle
{
public bool LeftWheelAttached;
public bool RightWheelAttached;
}
I would like to only store MotorcycleAxle objects in a Motorcycle object's Axles array, and CarAxle objects in a Car object's Axles array. The problem is there is no way to override the array in the subclass to force one or the other. Ideally something like the following would be valid for the Motorcycle class:
class Motorcycle : Vehicle
{
public override List<MotorcycleAxle> Axles;
}
but the types have to match when overriding. How can I support this architecture? Will I just have to do a lot of run-time type checking and casting wherever the Axles member is accessed? I don't like adding run-time type checks because you start to lose the benefits of strong typing and polymorphism. There have to be at least some run-time checks in this scenario since the WheelAttached and Left/RightWheelAttached properties depend on the type, but I would like to minimize them.
Use more generics
abstract class Vehicle<T> where T : Axle
{
public string Name;
public List<T> Axles;
}
class Motorcycle : Vehicle<MotorcycleAxle>
{
}
class Car : Vehicle<CarAxle>
{
}
abstract class Axle
{
public int Length;
public void Turn(int numTurns) { ... }
}
class MotorcycleAxle : Axle
{
public bool WheelAttached;
}
class CarAxle : Axle
{
public bool LeftWheelAttached;
public bool RightWheelAttached;
}
2 options spring to mind. 1 is using generics:
abstract class Vehicle<TAxle> where TAxle : Axle {
public List<TAxle> Axles;
}
The second uses shadowing - and this assumes you have properties:
abstract class Vehicle {
public IList<Axle> Axles { get; set; }
}
class Motorcyle : Vehicle {
public new IList<MotorcycleAxle> Axles { get; set; }
}
class Car : Vehicle {
public new IList<CarAxle> Axles { get; set; }
}
void Main() {
Vehicle v = new Car();
// v.Axles is IList<Axle>
Car c = (Car) v;
// c.Axles is IList<CarAxle>
// ((Vehicle)c).Axles is IList<Axle>
The problem with shadowing is that you have a generic List. Unfortunately, you can't constrain the list to only contain CarAxle. Also, you can't cast a List<Axle> into List<CarAxle> - even though there's an inheritance chain there. You have to cast each object into a new List (though that becomes much easier with LINQ).
I'd go for generics myself.
I asked a similar question and got a better answer, the problem is related to C#'s support for covariance and contravariance. See that discussion for a little more information.

Categories

Resources