2009-02-18 200 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(); 
沒問題

希望有幫助