views:

1847

answers:

5

I have an interface, and two classes that implements the interface. The classes have generic types. I would like to clone from an instance of one class to the other.

interface IFoo
{
    // stuff
}

class Foo<T> : IFoo
{
    // foo stuff
    // ifoo implementation
}

class Bar<T> : IFoo
{
    // bar stuff
    // ifoo implementation
}

I have a Foo and would like a Bar. Bar has a copy constructor taking a parameter of IFoo. I created an extension method to implement the clone:

public static Bar<T> Clone<T>(this IFoo foo) 
{
    return new Bar<T>(foo);
}

Calling the method requires the type:

someFoo.Clone<T> ...

Is there a way to omit declaring the type when calling the method by modifying the extension method, or any other way, to allow the the instance to just be passed in without caring about its underlying type?

Update Here is how this is being used to better illustrate the situation.

In a method I iterate a collection and return an enumeration of IFoo. In the method I look at an attribute of the source collection and determine the type of the Foo.

IFoo foo = null;

string type = element.Attribute("Type").Value;
switch (type)
{
    case "int":
        foo = new Foo<int>();
        break;

    case "string":
        foo = new Foo<string>();
        break;

    // etc
}
// other stuff

yield return foo;

The calling method has a List. Later I select individual items from this list for use, at which point I would like a Bar instead of a Foo. When selecting from the list the instances are of type IFoo, as in they only see the extension methods for "this IFoo foo". I do not want to cast the IFoo to a Foo, that would require re-declaring the type of T. I would just like to have Foo tell Bar what it is. Is this possible?

A: 

Will this help for inspiration?: http://stackoverflow.com/questions/469982/how-would-you-improve-this-shallow-copying-class

Essentially it's a generic reflection-based property copying method. Try it out.

Neil Barnwell
A: 

If it works for your scenario you could have an IFoo<T>. Also if you don't mind having specific extension methods, you could just receive an Foo<T>. You really need to pass something that references the T so the compiler can infer the appropriate type.

eglasius
A: 

When you need complete control over your deep copy clone, this pattern is very good:

public class FooBase
{
    private int x;

    public FooBase() { /* standard contructor */ }

    protected FooBase(FooBase clone)
    {
        this.x = clone.x;
    }

    public FooBase Clone() { return new FooBase(this); }
}

public class Foo : FooBase
{
    private int y;

    public Foo() { /* standard contructor */ }

    protected Foo(Foo clone) : base(clone)
    {
        this.y = clone.y;
    }

    public Foo Clone() { return new Foo(this); }
}

Define protected contructor for cloning - so derived classes can clone values in base class. This pattern must be written by hand (or generated with a help of good T4 template) but is very good for deep cloning.

Update: I think I have misunderstood the question and already have cloning implemented. Freddy is right - compiler must knew which type it should infer for and it cannot do it from IFoo type. It can do it in (this Foo< T > foo) though.

Jozef Izso
A: 

Try defining the method as such

public static Bar<T> Clone<T>(this Foo<T> foo)
{
    return new Bar<T>(foo);
}

This way, the parameter would have a generic type and the compiler would have a source for inferring the type from.

configurator
+1  A: 

So you have everything ok but you want to be able to use the syntax

someFoo.Clone()

instead of

someFoo.Clone<int>()

you want the int to be implied rather than having to put it ther explicitly?

The reason you can't do that in your code example is that IFoo doesn't reference the generic type T that you need in order to create Bar<T>.

I would suggest that you really need another interface: IFoo<T>

If you had that, and your extension method looks like this:

public static Bar<T> Clone<T>(this IFoo<T> foo) 
{
    return new Bar<T>(foo);
}

Then you will have no problem using

IFoo<int> someFoo = new Foo<int>();
Bar<int> someBar = someFoo.Clone();

Hope that helps

Jero