2009-02-18 37 views
5

Arabirim ve arabirimi uygulayan iki sınıfım var. Sınıflar genel tiplere sahiptir. Bir sınıfın örneğinden diğerine kopyalamak istiyorum.C# Genel Kopya Kurucu

interface IFoo 
{ 
    // stuff 
} 

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

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

Bir Foo'm var ve bir Bar istiyorum. Bar IFoo bir parametre alarak bir kopya kurucu vardır. Ben klon uygulamaya bir uzantısı yöntemi oluşturuldu: uzatma yöntemi değiştirerek yöntemi çağrılırken türünü ilan atlamak için bir yolu var mı

someFoo.Clone<T> ... 

: yöntemin çağrılması

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

türünü gerektirir ya da başka herhangi bir şekilde, vakanın temel türünü umursamadan geçmesine izin vermek için?

Güncelleştirme Bu, durumu daha iyi göstermek için nasıl kullanılmakta olduğunu gösterir.

Bir yöntemde bir koleksiyon yineliyorum ve bir IFoo numarasına dönün. Yöntemde, kaynak koleksiyonunun bir niteliğine bakıyorum ve Foo'nun türünü belirledim.

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; 

Arama yönteminin bir listesi vardır. Daha sonra, bu listeden kullanım için tek tek öğeleri seçiyorum, bu noktada Foo yerine bir Bar istiyorum. Listeden seçerken, örnekler yalnızca "bu IFoo foo" için uzantı yöntemlerini gördükleri gibi IFoo tipindedir. IFoo'yu bir Foo'ya dökmek istemiyorum. Bu, T. tipini yeniden ilan etmeyi gerektirecektir. Sadece Foo'nun Bar'a ne olduğunu söylemek istiyorum. Mümkün mü?

+0

Yardımcı olurum Belki de bir şey özlüyorum, ama eğer ur uzantısı fonksiyonu bir IFoo al, bu Foo türünde bir Bar içine "Klonla" nasıl gerekiyor? –

+0

Tek düşündüğüm, IFoo özelliklerinin Foo'dan Bar'a kopyalanan değerleridir. – blu

cevap

0

Eğer senaryonuz için çalışıyorsa, bir IFoo<T> olabilir. Belirli bir uzantı yöntemine sahip olmanıza da gerek yoksa, bir Foo<T> alabilirsiniz. Gerçekten de, T'ye referans veren bir şeyi iletmeniz gerekir, böylece derleyici uygun türden çıkarım yapabilir. Eğer derin kopya klonu üzerinde tam kontrol gerektiğinde

0

, bu desen çok iyidir:

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

Klonlama için korumalı contructor tanımla - bu yüzden türetilmiş sınıfları temel sınıf değerleri kopyalayabilirsiniz. Bu kalıp elle yazılmalıdır (veya iyi bir T4 şablonunun yardımıyla oluşturulur), ancak derin klonlama için çok iyidir.

Güncelleştirme: Sanırım soruyu yanlış anladım ve zaten klonlama uygulanmış. Freddy haklı - derleyici hangi türden bir sonuç çıkaracağını bilmeli ve IFoo türünden yapamaz. Ancak (bu Foo < T> foo)'da yapabilir.Bu tür

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

Bu şekilde olarak metodu tanımlama

0

deneyin parametre genel bir tür olurdu ve derleyici tipinden çıkarım için bir kaynak olacaktır.

2

Yani tamam her şey var ama açıkça ther koymak zorunda ziyade ima edilmesi tamsayıMaksimumDeger istediğiniz

someFoo.Clone<int>() 

ait

someFoo.Clone() 

yerine sözdizimi kullanmak mümkün istiyorum ?

Kod örneğinizde bunu yapamayacağınız nedeni, IFoo'nun Bar<T> oluşturmak için ihtiyaç duyduğunuz genel T türüne başvurmamasıdır.

Ben gerçekten başka bir arayüze ihtiyaç öneririm

: Bunu vardı ve uzatma yöntemi gibiyse bu IFoo<T>

: Eğer

IFoo<int> someFoo = new Foo<int>(); 
Bar<int> someBar = someFoo.Clone(); 
kullanarak sorun olacaktır

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

İlgili konular