C#通用复制构造函数

时间:2009-02-18 23:04:30

标签: c# interface clone generics

我有一个接口,以及两个实现接口的类。这些类具有泛型类型。我想从一个类的实例克隆到另一个类。

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它是什么。这可能吗?

5 个答案:

答案 0 :(得分:2)

所以你有一切都好,但你希望能够使用语法

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

希望有所帮助

答案 1 :(得分:0)

这会有助于灵感吗?:How would you improve this shallow copying class?

本质上,它是一种基于反射的通用属性复制方法。尝试一下。

答案 2 :(得分:0)

如果它适用于您的方案,您可以拥有IFoo<T>。此外,如果您不介意使用特定的扩展方法,则只能收到Foo<T>。您确实需要传递引用T的内容,以便编译器可以推断出合适的类型。

答案 3 :(得分: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模板的帮助下生成),但非常适合深度克隆。

更新:我认为我误解了这个问题并且已经实施了克隆。 Freddy是对的 - 编译器必须知道它应该推断出哪种类型,并且它不能从IFoo类型中做到。它可以在(这个Foo&lt; T&gt; foo)中完成。

答案 4 :(得分:0)

尝试定义方法

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

这样,参数将具有泛型类型,并且编译器将具有用于推断类型的源。