2009-02-18 149 views
5

我有一个接口和两个实现接口的类。这些类具有泛型类型。我想从一个类的实例克隆到另一个类。C#泛型拷贝构造函数

interface IFoo 
{ 
    // stuff 
} 

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

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

我有一个Foo,想要一个酒吧。 Bar有一个带IFoo参数的拷贝构造函数。 我创建一个扩展方法来实现克隆:

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

调用该方法需要的类型:

someFoo.Clone<T> ... 

有没有办法省略通过修改扩展方法调用方法时声明的类型或者其他任何方式来允许实例传入而不关心其基本类型?

更新 下面是如何使用它来更好地说明情况。

在一个方法中,我迭代一个集合并返回一个IFoo的枚举。在该方法中,我查看源集合的属性并确定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; 

调用方法有一个List。之后我从这个列表中选择单独的项目以供使用,此时我想要一个Bar而不是Foo。从列表中选择时,实例的类型是IFoo,因为它们只能看到“this IFoo foo”的扩展方法。我不想将IFoo投向Foo,这需要重新声明T的类型。我只希望Foo告诉Bar它是什么。这可能吗?

+0

也许我错过了一些东西,但如果哟乌尔扩展功能采取的IFoo,它怎么应该“克隆”成一间酒吧,如果它是Foo类型的? – 2009-02-18 23:09:47

回答

0

如果它适用于您的情况,您可以有一个IFoo<T>。此外,如果您不介意使用特定的扩展方法,则只能收到Foo<T>。你真的需要传递引用T的东西,所以编译器可以推断出适当的类型。

0

当你需要在你的深拷贝克隆完全控制,这种模式是非常好的:

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); } 
} 

定义保护构造器克隆 - 所以派生类可以在基类中克隆值。 这种模式必须手工编写(或在良好的T4模板的帮助下生成),但对于深度克隆非常有用。

更新:我想我误解了这个问题,并且已经实施了克隆。弗雷迪是对的 - 编译器必须知道它应该推断哪种类型,并且它不能从IFoo类型中完成。它可以在(这个Foo < T> foo)

0

尝试定义方法为这样

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

这种方式,参数将有一个一般类型和编译器将具有用于推断从类型的源极。

2

所以,你所拥有的一切OK,但你希望能够使用的语法

someFoo.Clone() 

,而不是

someFoo.Clone<int>() 

你想要的int值暗示,而不是把它疗法明确?

你不能这样做,在你的代码示例的原因是,IFoo的不引用您以创建Bar<T>需要泛型类型T。

我建议你真的需要另一个接口:IFoo<T>

如果你有这样的,你的扩展方法是这样的:

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

然后,你将不得不使用

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

希望有帮助