views:

103

answers:

6

In order to explain my problem here is an example

namespace CheckAbstarct
{

class Program
{
    static void Main(string[] args)
    {
        myAbstarctClass mac1 = ObjectFactory.ObjectCreator("aaa");
        myAbstarctClass mac2 = ObjectFactory.ObjectCreator("bbb");
        mac1.changeMyString();
        mac2.changeMyString();
        string myString = (string)mac2.returnMyObject();
        DateTime myObject = (DateTime) mac1.returnMyObject();

        object obj1 = mac1.returnMyObject();
        object obj2 = mac2.returnMyObject();

        myMethod(obj1);  //---> This is not compiling
        myMethod(obj2);  //---> This is not compiling

        myMethod(myString);  //---> works fine
        myMethod(myObject);  //---> works fine

        Console.ReadKey();
    }
    public static void myMethod(DateTime dt)
    {
    }
    public static void myMethod(string st)
    {
    }
}
abstract class myAbstarctClass
{
    protected string mMyString;
    public myAbstarctClass()
    {
        mMyString = "myAbstarctClass ";
    }
    public abstract void changeMyString();
    public abstract object returnMyObject();        
}

class MyNewAbstractClass1 : myAbstarctClass
{
    DateTime mObject;
    public MyNewAbstractClass1(string myString)
    {
        mMyString = myString;
        mObject = new DateTime().Date;
    }
    public override void changeMyString()
    {
        mMyString += " MyNewAbstractClass1";
        Console.WriteLine(mMyString);
    }
    public override object returnMyObject()
    {
        return mObject;
    }
}

class MyNewAbstractClass2 : myAbstarctClass
{
    string mString;
    public MyNewAbstractClass2(string myString)
    {
        mMyString = myString;
        mString = mMyString;
    }
    public override void changeMyString()
    {
        mMyString += " MyNewAbstractClass2";
        Console.WriteLine(mMyString);
    }
    public override object returnMyObject()
    {
        return mString;
    }
}

static class ObjectFactory
{
    public static myAbstarctClass ObjectCreator(string myString)
    {
        switch (myString)
        {
            case "aaa":
                return new MyNewAbstractClass1(myString);
            case "bbb":
                return new MyNewAbstractClass2(myString);
            default:
                return null;
        }
    }
}    
}

My problem is that in Main() I don't know what type the returnMyObject() method returns so I can't send it to MyMethod. Is there a way to cast the objects ??

+5  A: 

Because in your design of returnMyObject() you went back to the most common object references, you will have to find out in runtime:

if (obj1 is string)
     myMethod((string)obj1);  //--->cast it 
else if (obj1 is DateTime)
     myMethod((DateTime) obj1);
Henk Holterman
Why not use obj1.ToString()
Gage
@Gage: I was trying to show a pattern with 2 types. string is a bit privileged, didn't want to use that here. And ToString is not really better or faster here.
Henk Holterman
+4  A: 

You could check the object's type at runtime:

public static void myMethod(Object o)
{
    if (o is DateTime)
        myMethod((DateTime)o);
    else if (o is string)
        myMethod((string)o);
}

Although in your case, you might just as well pass a myAbstarctClass instance to myMethod, and then call returnMyObject() there.

Hollance
A: 

No, you have to either create switch with all possibilities, or something like Dictionary<Type, Delegate>

or you can just make myMethod(object obj)

it's called Multiple dispatch (http://en.wikipedia.org/wiki/Multiple_dispatch) and there are some libraries that can do it

Kikaimaru
+1  A: 

You can either use dynamic feature from C# 4.0 or change design to utilize some kind of double dispatch technique

        dynamic obj1 = mac1.returnMyObject();
        dynamic obj2 = mac2.returnMyObject();
desco
+1  A: 

Use Polymorphism mechanisms so you don't need to know the type of object.

Make myMethod an abstract method of myAbstarctClass and provide implementations in both MyNewAbstractClass1 and MyNewAbstractClass2.

Modify myAbstractClass1.returnMyObject() to return myAbstarctClass (not object).

The test code in Main can then be written:

...
myAbstarctClass obj1 = mac1.returnMyObject();
myAbstarctClass obj2 = mac2.returnMyObject();

obj1.myMethod();        // calls MyNewAbstractClass1.myMethod()
                        // no if statement required!

obj2.myMethod();        // calls MyNewAbstractClass2.myMethod()
                        // no if statement required!

Console.ReadKey();

Edit: This can be further simplified, since the returnMyObject() methods are no longer necessary - they just return the object you already have. The test code is now simply:

mac1.myMethod();
mac2.myMethod();

// etc...
Console.ReadKey();
MatthewD
Thanks but the idea is that MyMethod is a method that should work on information (in the futur) that I don't want the myAbstracts object to know about
Without any information about what myMethod is doing it's rather difficult to provide a reasonable solution to your problem. I have one other idea though, which I'll post as a new answer.
MatthewD
A: 

Since you seem to be using your class as a container for a type (eg. DateTime, string), perhaps Generics would a be better choice than Inheritance:

namespace CheckAbstract
{
    class Program
    {
        static void Main(string[] args)
        {
            myTemplateClass<DateTime> mac1 = new myTemplateClass<DateTime>(new DateTime().Date);
            myTemplateClass<string> mac2 = new myTemplateClass<string>("cat dog");

            mac1.changeMyString();
            mac2.changeMyString();
            string myString = (string)mac2.returnMyObject();
            DateTime myObject = (DateTime) mac1.returnMyObject();

            myMethod<string>(myString);
            myMethod<DateTime>(myObject);

            Console.ReadKey();
        }

        public static void myMethod<T>(T obj)
        {
        }
    }

    class myTemplateClass<T>
    {
        T mObject;
        string mMyString;
        public myTemplateClass(T init)
        {
            mMyString = init.ToString();
            mObject = init;
        }
        public void changeMyString()
        {
            mMyString += " " + mObject.ToString();
            Console.WriteLine(mMyString);
        }
        public T returnMyObject()
        {
            return mObject;
        }
    }
}
MatthewD