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;

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

4

5 回答 5

2

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

someFoo.Clone()

代替

someFoo.Clone<int>()

你希望 int 被暗示而不是明确地把它放在那里?

您在代码示例中不能这样做的原因是 IFoo 没有引用您创建所需的泛型类型 T Bar<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();

希望有帮助

于 2009-02-19T04:41:15.580 回答
0

这对灵感有帮助吗?:你会如何改进这个浅拷贝课程?

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

于 2009-02-18T23:11:12.003 回答
0

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

于 2009-02-18T23:30:35.703 回答
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)中做到这一点。

于 2009-02-18T23:38:34.217 回答
0

尝试这样定义方法

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

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

于 2009-02-19T00:56:26.493 回答