Generic function on a list of derived class - c#

I feel my question is pretty dumb, or another way to put it is : I'm too lost in my code to see a workaround for now. Stay too long on a problem, and your vision becomes narrower and narrower ><. Plus I'm not good enough with inheritance, polymorphism and so
Here is the idea : I have multiple list of derived class, and I would like to call generic functions on those lists (accesing and modifying members of the base class). I feel there is something to do with inheritance, but I don't manage to make it work as I want for now .
Here is a very simple example of what I'm intending to do :
class Baseclass
{
public int ID;
public string Name;
}
class DerivedClass1 : Baseclass
{
}
private void FuncOnBase(List<Baseclass> _collection)
{
// ...
foreach (Baseclass obj in _collection)
{
++obj.ID;
}
// ...
}
private void FuncTest()
{
List<DerivedClass1> collection1 = new List<DerivedClass1>();
collection1.Add(new DerivedClass1() { ID = 1 });
collection1.Add(new DerivedClass1() { ID = 2 });
collection1.Add(new DerivedClass1() { ID = 3 });
FuncOnBase(collection1); // ==> forbidden, cannot convert the derived class list to the base class list
}

Gotta love variance. A List<DerivedClass1> is not a List<Baseclass> - otherwise, FuncOnBase could attempt to add a Baseclass to the list, and the compiler wouldn't spot it.
One trick is to use a generic method:
private void FuncOnBase<T>(List<T> _collection) where T : Baseclass
{
// ...
foreach (T obj in _collection)
{
obj.ID++;
}
// ...
}
In terms of the example I presented above - note that we are able to add a T to the list; useful in particular if we add the T : new() constraint, or pass in (for example) a params T[].
Note also that IEnumerable<T> becomes covariant in C# 4.0 / .NET 4.0, so if you passed in just an IEnumerable<Baseclass> (rather than a list) it would work "as is":
private void FuncOnBase(IEnumerable<Baseclass> _collection)
{
///...
}

If you're only doing a foreach, declare FuncOnBase(IEnumerable<Baseclass> collection), which you can call from FuncTest like this:
FuncOnBase(collection1.Cast<Baseclass>());
When you declare a method with a List<T> parameter but only use its IEnumerable<T> features, you're adding API constraints that mean nothing in your code.

Related

Apply generic visitor to generic derived class of non-generic base class

Currently I have something like this:
public abstract class Base {...}
public class Derived<T> : Base {...}
class Visitor {
public static void Visit<T>(Derived<T> d) {
...
}
}
My question is, given a Base reference that I know is a Derived instance, how can I apply that Visit function to that object, using the correct generic instantiation? I understand that the answer will probably involve a type-checked dynamic downcast, to make sure that the object isn't some other type derived from base, which is all fine. I assume the answer involves reflection, which is also fine, though I'd prefer if there was a way to do it without reflection.
It's also ok if the answer involves an abstract method on Base and Derived; I do have enough control of the classes to add that. But at the end of the day, I need to call a generic function, correctly instantiated with the T of the Derived type.
Sorry if this is an easy question; I come from a C++ background, where my instinct would be to use a CRTP or something else like that, which isn't possible in C#.
EDIT:
Here's an example of what I need to be able to do:
Base GetSomeDerivedInstance() { ...; return new Derived<...>(); }
var b = GetSomeDerivedInstance();
// This is the line that needs to work, though it doesn't necessarily
// need to have this exact call signature. The only requirement is that
// the instantiated generic is invoked correctly.
Visitor.Visit(b);
In my opinion, answers involving double-dispatch and More Classes are going to be superior than using reflection to do what inheritance should do for you.
Normally this means defining an 'accept' method on the visitable class, which simply calls the correct Visit method from the visitor.
class Base
{
public virtual void Accept(Visitor visitor)
{
visitor.Visit(this); // This calls the Base overload.
}
}
class Derived<T> : Base
{
public override void Accept(Visitor visitor)
{
visitor.Visit(this); // this calls the Derived<T> overload.
}
}
public class Visitor
{
public void Visit(Base #base)
{
...
}
public void Visit<T>(Derived<T> derived)
{
...
}
}
Then you can do what you mentioned in your question, with a small modification:
Base b = createDerived();
b.Accept(new Visitor());
If your visit method is a static class that you can't change for whatever reason, you could always wrap this into a dummy instance visitor class which calls the right static method.
(Edited for clarity)
The following will use a variable called "anyvalue" whose type is only known at run-time. Then we'll create an instance of your Derived class based on the type of anyvalue. Once we have that instance, we can use reflection to get the correct Visit method.
var anyvalue = 5; // This value could have come from anywhere.
...
var derivedType = typeof (Derived<>).MakeGenericType(anyvalue.GetType());
var dvalue = Activator.CreateInstance(derivedType);
var method = typeof(Visitor).GetMethod("Visit");
var genericMethod = method.MakeGenericMethod(new[] { anyvalue.GetType() });
genericMethod.Invoke(null, new [] { dvalue });
What is a little confusing is that this is a skeletal example and you do not use the original value for anything other than getting a run-time type. In the real world implementation, I would assume a constructor would use that value to set internal state in the Derived instance. That is not covered here because that is not part of the question that was asked.
UPDATE:
I think this will do what you want. Note that I created the itemarray so that we would have some run-time values. They have to be created somewhere. So whether they are passed in as object[] or provided some other way, they had to be constructed with a type specifier somewhere. Also, this assumes that Derived<> is the only derived class. Otherwise, this is not safe code.
var itemarray = new Base[] { new Derived<int>(), new Derived<string>() };
foreach (var baseObject in itemarray)
{
var derivedType = baseObject.GetType();
var visitMethod = typeof(Visitor)
.GetMethod("Visit")
.MakeGenericMethod(derivedType.GetGenericArguments());
visitMethod.Invoke(null, new[] { baseObject });
}
The Accept approach does seem a bit more manageable. My goal was to answer the question you asked without passing judgment on your approach. I have needed to use this approach several times. I wrote an entity framework about 9 years ago. I had a really hard time doing exactly what you are trying to do. I created base classes that were not generic so that I could share basic functionality regardless of the generic type. It proved challenging. I am not sure I would do it the same way now. I'd probably investigate a few patterns just as you are doing.
You should be able to do something like the following:
Base foo = new Derived<int>();
var method = typeof(Visitor).GetMethod("Visit", BindingFlags.Public | BindingFlags.Static);
method.MakeGenericMethod(foo.GetType().GenericTypeArguments.First()).Invoke(null, new[] {foo});
Perhaps you're meaning something like this?
public class Derived<T>
{
}
public abstract class Derivable<T>
{
public Derived<T> CreateDerived()
{
return new Derived<T>();
}
}
public class Foo : Derivable<Foo>
{
}
class Visitor
{
public static void Visit<T>(Derived<T> obj)
{
Console.Out.WriteLine("Called!");
}
}
void Main()
{
var obj = new Foo();
var derived = obj.CreateDerived();
Visitor.Visit(derived);
}
If the creation of the Derived<T> is T-specific, then you'd make the CreateDerived method abstract and implement it for each T. Or use an IDerivable<T> interface instead if you don't want it as your base class.

Dynamic selection of method based on runtime parameter type

I've seen similar questions/answers for this posted in the past, but mine differs slightly from the others that I've seen.
Essentially, I have a common interface and several classes that implement/inherit from it. Then, in a separate class, I have methods that must act upon objects given by the interface IObject. However, each of them must be acted upon in different ways, hence why there is a separate declaration of the method for each concrete type that extends IObject.
class IObject
{
...
}
class ObjectType1 : IObject
{
...
}
class ObjectType2 : IObject
{
...
}
class FooBar
{
void Foo (ObjectType1 obj);
void Foo (ObjectType2 obj);
}
Now, to me, one obvious solution is to take advantage of dynamic binding by placing the method Foo inside each individual class, which would automatically choose at runtime the correct Foo to execute. However, this is not an option here, because I am defining multiple models for how to act upon these objects, and I would rather encapsulate each individual model for handling objects in its own class, rather than stuff all of the models into the object classes.
I found this post which shows how to use a dictionary to dynamically choose at runtime the correct method implementation. I'm fine with this approach; however, suppose that I have to perform a dispatch like this once in every model. If I only have IObject and its concrete implementations, is there any way to generalize this approach so that I could call methods of any name based on the runtime type of the objects?
I know this is probably an unclear question, but I would greatly appreciate any help.
The dynamic keyword is actually really good at this:
void Main()
{
var foobar = new FooBar();
foreach(IObject obj in new IObject[]{ new ObjectType1(), new ObjectType2()})
{
foobar.Foo((dynamic)obj);
}
// Output:
// Type 1
// Type 2
}
class IObject
{
}
class ObjectType1 : IObject
{
}
class ObjectType2 : IObject
{
}
class FooBar
{
public void Foo (ObjectType1 obj) {
Console.WriteLine("Type 1");
}
public void Foo (ObjectType2 obj) {
Console.WriteLine("Type 2");
}
}
The code is super-simple, and it's got pretty decent performance.
you can just make one method that takes the interface type,then you check for the correcttype
and cast it
ObjectType1 obj1 = new ObjectType1();
foo(obj1);
void foo(IObject fm)
{
ObjectType1 cls;
if (fm is ObjectType1)
{
cls = fm as ObjectType1;
cls.ID = 10;
MessageBox.Show(cls.ID.ToString() + " " + cls.GetType().ToString());
}
}
thats because the classes implement IObject
,cls.ID is just an example you can put one property you implement.
Please try it and let me know....best wishes.

Generics and inheritance... Getting around having to specify the <T> type?

Well, I've had to rewrite this as I've been down voted five times for giving too much detail... Go figure!
class BaseModel
{
public T[] Get<T>()
{
// return array of T's
}
public T Find<T>(object param)
{
// return T based on param
}
public T New<T>()
{
// return a new instance of T
}
}
class BaseRow
{
private BaseModel _model;
public BaseRow(SqlDataReader rdr, BaseModel model)
{
// populate properties of inheriting type using rdr column values
}
public void Save()
{
// calls _model.Save(this);
}
}
I currently have a number of classes that inherit the BaseModel class. Each of the methods exposed by BaseModel will return an instance, or an array of instances of a type that inherits the BaseRow class.
At the moment, when calling the exposed methods on the BaseModel via an inheriting class, i.e.
using(DeviceModel model = new DeviceModel())
{
DeviceRow row = model.Find<DeviceRow>(1);
DeviceRow[] rows = model.Get<DeviceRow>();
DeviceRow newRow = model.New<DeviceRow>();
}
I have to specify the type (a class that inherits the BaseRow class), as the methods in BaseModel/BaseRow do not know/care what type they are, other than they inherit from BaseRow.
What I would like to do is find a way to remove the need to specify the without having to replicate code in every class that inherits BaseModel, i.e.
class DeviceModel : BaseModel
{
public DeviceRow Find(object param)
{
return this.Find<DeviceRow>(param);
}
}
Note: Unfortunately I am unable to implement or use any third party solutions. That said, I have tried using Castle Active Record/nHibernate and to be honest, they are very big and heavy for what should be a very simple system.
Hopefully I haven't provided "too much" detail. If I have, please let me know.
Thanks
If I were you, I'd suggest making BaseModel a generic class. In a situation of "can't win either way", the code you've removed to make others happy might have told me more about what you're doing (not a criticism by any stretch - I appreciate your position).
class BaseModel<T>
{
public virtual T[] Get()
{
// return array of T's
}
public virtual T Find(object param)
{
// return T based on param
}
public virtual T New()
{
// return a new instance of T
}
}
That's your base, and then you have inheritors like:
class DeviceModel : BaseModel<Device>
{
public override Device New()
{
return new Device();
}
}
Now, any generic operations you define in DeviceModel will default to returning or using strongly typed Device. Notice the virtual methods in the BaseModel class. In the base class methods, you might provide some basic operations predicated upon using T's or something. In sub-classes, you can define more specific, strongly typed behavior.
I'd also comment that you might want to pull back a little and consider the relationship of BaseModel and BaseRow. It appears that you're defining a parallel inheritance hierarchy, which can tend to be a code smell (this is where more of your code might have come in handy -- I could be wrong about how you're using this). If your ongoing development prospects are that you're going to need to add a FooRow every time you add a FooModel, that's often a bad sign.

Why cast to an interface?

In Jesse Liberty's Programming C# (p.142) he provides an example where he casts an object to an interface.
interface IStorable
{
...
}
public class Document : IStorable
{
...
}
...
IStorable isDoc = (IStorable) doc;
...
What is the point of this, particularly if the object's class implements the inteface anyway?
EDIT1: To clarify, I'm interested in the reason for the cast (if any), not the reason for implementing interfaces. Also, the book is his 2001 First Edition (based on C#1 so the example may not be germane for later versions of C#).
EDIT2: I added some context to the code
Because you want to restrict yourself to only methods provided by the interface. If you use the class, you run the risk of calling a method (inadvertently) that's not part of the interface.
There is only one reason when you actually need a cast: When doc is of a base type of an actual object that implements IStorable. Let me explain:
public class DocBase
{
public virtual void DoSomething()
{
}
}
public class Document : DocBase, IStorable
{
public override void DoSomething()
{
// Some implementation
base.DoSomething();
}
#region IStorable Members
public void Store()
{
// Implement this one aswell..
throw new NotImplementedException();
}
#endregion
}
public class Program
{
static void Main()
{
DocBase doc = new Document();
// Now you will need a cast to reach IStorable members
IStorable storable = (IStorable)doc;
}
}
public interface IStorable
{
void Store();
}
If the object implements the interface explicitly (public void IStorable.StoreThis(...)) that casting is the easiest way to actually reach the interface members.
I am not sure under what context the example was given in the book. But, you generally can type cast an object to interface to achieve multiple inheritance. I have given the example below.
public interface IFoo
{
void Display();
}
public interface IBar
{
void Display();
}
public class MyClass : IFoo, IBar
{
void IBar.Display()
{
Console.WriteLine("IBar implementation");
}
void IFoo.Display()
{
Console.WriteLine("IFoo implementation");
}
}
public static void Main()
{
MyClass c = new MyClass();
IBar b = c as IBar;
IFoo f = c as IFoo;
b.Display();
f.Display();
Console.ReadLine();
}
This would display
IBar implementation
IFoo implementation
It's pretty hard to tell without more of the context. If the variable doc is declared to be a type which implements the interface, then the cast is redundant.
Which version of the book are you reading? If it's "Programming C# 3.0" I'll have a look tonight when I'm at home.
EDIT: As we've seen in the answers so far, there are three potential questions here:
Why cast in the statement shown in the question? (Answer: you don't have to if doc is of an appropriate compile-time type)
Why is it ever appropriate to explicitly cast to an implemented interface or base class? (Answer: explicit interface implementation as shown in another answer, and also for the sake of picking a less specific overload when passing the cast value as an argument.)
Why use the interface at all? (Answer: working with the interface type means you're less susceptible to changes in the concrete type later on.)
The doc object might be of a type that implements members of IStorable explicitly, not adding them to the classes primary interface (i.e., they can only be called via the interface).
Actually "casting" (using the (T) syntax) does not make any sense since C# handles upcasts (cast to parent type) automatically (unlike F# for instance).
There are a lot of good answers here, but I don't really think they answer WHY you actually WANT to use the most restrictive interface possible.
The reasons do not involve your initial coding, they involve the next time you visit or refactor the code--or when someone else does it.
Let's say you want a button and are placing it on your screen. You are getting the button either passed in or from another function, like this:
Button x=otherObject.getVisibleThingy();
frame.add(x);
You happen to know that VisibleThingy is a button, it returns a button, so everything is cool here (no cast required).
Now, lets say that you refactor VisibleThingy to return a toggle button instead. You now have to refactor your method because you knew too much about the implementation.
Since you only NEED the methods in Component (a parent of both button and Toggle, which could have been an interface--same thing pretty much for our purposes), if you had written that first line like this:
Component x=(Component)otherObject.getVisibleThingy();
You wouldn't have had to refactor anything--it would have just worked.
This is a very simple case, but it can be much more complex.
So I guess the summary would be that an interface is a specific way to "View" your object--like looking at it through a filter...you can only see some parts. If you can restrict your view enough, the object can "Morph" behind your particular view and not effect anything in your current world--a very powerful trick of abstraction.
The best reason why you would cast to interfaces would be if you are writing code against objects and you don't know what concrete type they are and you don't want to.
If you know that you might come across an object that implements a specific interface you could then get the values out of the object without having to know the concrete class that this object is. Also, if you know that an object implements a given interface, that interface might define methods that you can execute to take certain actions on the object.
Here's a simple example:
public interface IText
{
string Text { get; }
}
public interface ISuperDooper
{
string WhyAmISuperDooper { get; }
}
public class Control
{
public int ID { get; set; }
}
public class TextControl : Control, IText
{
public string Text { get; set; }
}
public class AnotherTextControl : Control, IText
{
public string Text { get; set; }
}
public class SuperDooperControl : Control, ISuperDooper
{
public string WhyAmISuperDooper { get; set; }
}
public class TestProgram
{
static void Main(string[] args)
{
List<Control> controls = new List<Control>
{
new TextControl
{
ID = 1,
Text = "I'm a text control"
},
new AnotherTextControl
{
ID = 2,
Text = "I'm another text control"
},
new SuperDooperControl
{
ID = 3,
WhyAmISuperDooper = "Just Because"
}
};
DoSomething(controls);
}
static void DoSomething(List<Control> controls)
{
foreach(Control control in controls)
{
// write out the ID of the control
Console.WriteLine("ID: {0}", control.ID);
// if this control is a Text control, get the text value from it.
if (control is IText)
Console.WriteLine("Text: {0}", ((IText)control).Text);
// if this control is a SuperDooperControl control, get why
if (control is ISuperDooper)
Console.WriteLine("Text: {0}",
((ISuperDooper)control).WhyAmISuperDooper);
}
}
}
running this little program would give you the following output:
ID: 1
Text: I'm a text control
ID: 2
Text: I'm another text control
ID: 3
Text: Just Because
Notice that I didn't have to write any code in the DoSomething method that required me to know anything about all the objects I was working on being concrete object types. The only thing that I know is that I'm working on objects that are at least an instance of the Control class. I can then use the interface to find out what else they might have.
There's a million different reasons that you would take this approach with interfaces on your objects but it gives you a loose way to access your objects without having to know exactly what it is.
Think of all the credit cards in the world, every company makes their own, the interface is the same though, so every card reader can have a card swiped through it that follows the standard. Similar to the usage of interfaces.
As has been noted, the casting is superfluous and not necessary. However, it is a more explicit form of coding which would be useful to beginners in aiding their understanding.
In an introductory textbook, it is best to explicitly act, rather than let the compliler do things implicitly, which would be more confusing for beginners.
The "doc" is not of type "IStorable" so it would be confusing for beginners to see that it is being assigned to a isDoc. By explicitly casting, the author (of the book and of the code) is saying that a document can be casted to an IStorable object, but it is NOT THE SAME as an IStorable object.
The point is, the object (where did you get it?) may not implement the interface, in which case an exception is thrown which can be caught and dealt with. Of course you can use the "is" operator to check, and the "as" operator to cast instead of the C-style cast.
To allow for the most decoupling between pieces of code...
See the following article for more:
Interfaces
The main reason you would explicitly cast to an interface is if the members of the interface are implemented explicitly (i.e. with fully-qualified names in the form of InterfaceName.InterfaceMemberName). This is because when you fully-qualify them with the interface name, those members are not actually part of the implementing class's API. You can only get to them via casting to the interface.
Here's an example you can run as-is:
using System;
public interface ISomethingDoer {
void DoSomething();
}
public class ThingA : ISomethingDoer {
public void DoSomething(){
Console.WriteLine("ThingA did it!");
}
}
public class ThingB : ISomethingDoer {
// This is implemented explicitly by fully-qualifying it with the interface name
// Note no 'scope' here (e.g. public, etc.)
void ISomethingDoer.DoSomething(){
Console.WriteLine("ThingB did it!");
}
}
public static class Runner {
public static void Main(){
var a = new ThingA();
a.DoSomething(); // Prints 'ThingA did it!'
var b = new ThingB();
b.DoSomething(); // NOTE: THIS WILL NOT COMPILE!!!
var bSomethingDoer = (ISomethingDoer)b;
bSomethingDoer.DoSomething(); // Prints 'ThingB did it!'
}
}
HTH!

Nested generic collections: How to implement reference from item to container?

While implementing a design using nested generic collections, I stumbled across those limitations apparently caused by C#'s invariant Generics:
Cannot convert from 'Collection<subtype of T> to 'Collection<T>'
That means, the following will not work, apparently due to the invariance of Generics:
class Outer<TInner, TInnerItem> where TInner : Inner<TInnerItem>
{
public void Add(TInner item)
{
item.Outer = this; // ERROR:
// Cannot implicitly convert from Outer<TInner, TInnerItem>
// to Outer<Inner<TInnerItem>, TInnerItem>
}
}
class Inner<TInnerItem> : ICollection<TInnerItem>
{
Outer<Inner<TInnerItem>, TInnerItem> _outer;
public Outer<Inner<TInnerItem>, TInnerItem> Outer
{
set { _outer = value; }
}
}
(In the actual code, both Inner<> and Outer<> implement ICollection<>.)
I need the Inner<> objects to have a reference to its container collection in order to access some of its data.
How would you implement these nested collections, preferably using a generic approach as outlined above? How would you set the reference to the container collection in the Inner<> class?
Cheers!
Introducing a (possibly abstract) base class which is not dependant on TInner may help you:
abstract class OuterBase<TInnerItem>
{
}
class Outer<TInner, TInnerItem> : OuterBase<TInnerItem> where TInner : Inner<TInnerItem>
{
public void Add(TInner item)
{
item.Outer = this; // Compiles
}
}
class Inner<TInnerItem> : ICollection<TInnerItem>
{
OuterBase<TInnerItem> _outer;
public OuterBase<TInnerItem> Outer
{
set { _outer = value; }
}
}
Or wait for C# 4.0, which introduces co/contra-variant generic interfaces.
The language can't let you convert from Collection<subtype of T> to Collection<T>
Let me explain why.
Imagine you have a Collection<subT> and cast it to Collection<T>. That's ok, since subT inherits from T.
When you retrieve an object from collection_of_T, you're assured that it's ok.
Later, add a T object to collection_of_T. Now you have, in collection_of_subT an object which is not a subT. Whoops.
In order to achieve what you want, you must create a new Collection alltogether.
Collection<T> collection_of_T = new Collection<T>(collection_of_subT);
Which probably is not good for you. Do you really need the TInner generic argument in the Outer class? Would it be possible to replace with Inner<TInnerItem> in the rest of the code instead?

Categories

Resources