views:

75

answers:

4

Hello =)

I'm new at the C# thing.... (.net 3.5)

I want a Dictionary to hold two different types of object, one of the type is generic. while iterating through the list, i will call methods like add and clone. I have tried it with a base class and subclasses....

namespace ConsoleApplication1 {
    class Element{
    }
    class Child1 : Element {
        public Child1 Clone() { return clone; }
    }
    class Child2<T> : Element {
        public Child2<T> Clone() { return clone; }
    }
    class Program {
        static void Main(string[] args) {
            Dictionary<string, Element> d = new Dictionary<string, Element>();
            d.Add("c1",  new Child1());
            d.Add("c2s", new Child2<string>());
            d.Add("c2i", new Child2<int>());
            foreach (KeyValuePair<string, Element> kvp in d) {
                Element e = kvp.Value.Clone();
            }
        }
    }
}

Is there a way or solution for my needs?

Thanks! Anna

+2  A: 

Since the type of .Value you get out of your dictionary is Element, you need to make sure Element defines all operations it should have, like your Clone method.

I would:

  1. Make Clone virtual, and add it to Element (or make Element abstract, and Clone abstract instead of virtual)
  2. Override Clone in both Child1 and Child2

This way, the code kvp.Value.Clone() would call the right Clone method depending on the object returned from the dictionary.

Lasse V. Karlsen
+3  A: 

You could make Clone either abstract or virtual on the base-type (Element), and override it in the derived types, but you can't change the return type when overriding, so it would have to be Element (nothing more specific). You can redeclare methods (new...), but that gets messy, and you can't override and new a method by the same name/signature in the same type.

But if you're happy for the return type to be Element...

abstract class Element{
    public abstract Element Clone();
}
class Child1 : Element {
    public override Element Clone() { return /* your code */; }
}
class Child2<T> : Element {
    public override Element Clone() { return /* your code */; }
}
Marc Gravell
A: 

Don't create a class hierarchy just for the sake of being able to add different objects to one dictionary though.

If the classes don't have a decent enough hierarchical relationship, you would be better off using an interface like ICloneable, which is already available in the .NET framework.

Then, simply instantiate your Dictionary like:

Dictionary<string, ICloneable> d = new Dictionary<string, ICloneable>();

It's more flexible. Creating a hierarchy for the sake of the commonality of being able to perform Clone(), is not the right solution IMO.

Wim Hollebrandse
A: 

Though I agree with Wim, that implementing ICloneable is probably the better solution, rather than trying to enforce a non-existing class hierachy, please be aware that ICloneable is considered a "bad API" as it does not specify whether it uses shallow- or deepcopy semantics (see for instance http://pro-thoughts.blogspot.com/2009/02/write-deep-clone-forget-about.html or do a google search for "ICloneable C# bad API"

Mads Ravn