C#通用复制构造函数

5

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

interface IFoo
{
    // stuff
}

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

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

我有一个Foo对象,想要一个Bar对象。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;

调用方法有一个列表。之后我从这个列表中选择单个项目以供使用,此时我想要的是 Bar 而不是 Foo。当从列表中进行选择时,实例的类型为 IFoo,因为它们只能看到“this IFoo foo”的扩展方法。我不想将 IFoo 强制转换为 Foo,因为那会要求重新声明 T 的类型。我只想让 Foo 告诉 Bar 它是什么。这可能吗?


也许我漏掉了什么,但如果您的扩展函数接受一个IFoo,那么如果它是Foo类型,它应该如何“克隆”它到Bar中呢? - Asaf R
我所关心的是将IFoo属性中的值从Foo复制到Bar。 - blu
5个回答

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

希望能帮上忙。

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类型中推断出来。不过在(this Foo< T > foo)中可以做到。


0

尝试将该方法定义为如下形式

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

这样,参数将具有通用类型,编译器将有一个源来推断类型。

0

0
如果适用于您的场景,您可以拥有一个IFoo<T>。此外,如果您不介意具有特定的扩展方法,您可以只接收一个Foo<T>。您确实需要传递引用T的内容,以便编译器可以推断出适当的类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接