-1

I have the following classes:

class MyObject { }
class MyObject2 { }

interface Parent<T>
{
    void DoSomething(T myObj);
}

class Child1 : Parent<MyObject1>
{
    public void DoSomething(MyObject1 myObj) { }
}

class Child2 : Parent<MyObject2>
{
    public void DoSomething(MyObject2 myObj) { }
}

I want to create a factory method which return the parent but I get the following casting error

Cannot implicitly convert type 'Child1' to 'Parent'. An explicit conversion exists (are you missing a cast?)

static Parent<object> Factory()
    {
        return new Child1();
    }

Is there any workaround for this?

Tsahi
  • 445
  • 4
  • 22
  • `but I get a casting error when I try to cast from Child1 to Parent` so what is the error.. how are we supposed to know if you don't post the relevant error that's being returned..? – MethodMan Apr 11 '16 at 18:25
  • `Parent` != `Parent`. You're going to have to [create some interfaces](http://stackoverflow.com/questions/6623188/pattern-for-exposing-non-generic-version-of-generic-interface) if you want to use `Parent` in a non-generic context. (i.e. analogous to how `List` implements the non-generic `IList`) – Kirk Woll Apr 11 '16 at 18:29
  • How should clients use the returned object if they don't know what `T` is? – Lee Apr 11 '16 at 18:35
  • What you are attempting here is co-variance. You can only do that with interfaces. And you should only do it if the type is only used for output (not the case for your `T` which is used of input). But more importantly casting to `object` completely defeats the purpose of generics and you should really reconsider your design. – juharr Apr 11 '16 at 18:41

3 Answers3

5

What you're asking for isn't possible. It doesn't make sense to refer to a Parent<MyObject1> as a Parent<object>. If you have a string, you can't pass it to a method whose signature is DoSomething(MyObject1). You need to find another way to do what you're trying to do.

Tim S.
  • 55,448
  • 7
  • 96
  • 122
0

I didn't test this fully so there may be some mistakes but as far as I know you could achieve this, though a bit sloppy, create an interface like:

public interface Parent
{
    void DoSomething(object myObj);
}

And an abstract class like

public abstract class BaseParent<T> : Parent<T>, Parent
{
    public abstract void DoSomething(T myObj);

    public void DoSomething(object myObj)
    {
        T obj = myObj as T;
        if (obj != null)
        {
            DoSomething(obj);
            return;
        }

        // Do something to handle null values, unexpected values
    }
}

Modify Child1 and Child2 to implement the abstract class. i.e.:

class Child1 : BaseParent<MyObject1>

You should be able to cast Child1 or Child2 to "Parent".

Note this does not handle the case when myObj is a value of type T that is null, so if you need to accept null values you need to do a little more.

(And it's questionable if you really SHOULD be doing this in the first place, if you pass an object that is not the correct type... what is supposed to happen?)

Robert Noack
  • 1,286
  • 14
  • 22
0

This is quite interesting, mixing generics and sub classing. But in my view you don't need two child classes, since they are actually the same class only differing by the generic parameter.

If you write

Public static Parent<MyObject1> Factory()
{
   Return new Child1();
}

Then error goes away. Essentially meaning the return Type should be concrete type since the factory method itself is non generic.

So you need to make the factory method as generic, like so:

Public static Parent<T> Factory<T>() { return (Parent<T>)new Child1(); }

You are actually trying to implement abstract factory, an abstract factory has two parameters for object creation, in your case one is the generic type and the other is the parameter based on which the factory method would create the object. So I suggest look at abstract factory design pattern.

NatarajC
  • 123
  • 6