2009-02-18 25 views
5

Ho un'interfaccia e due classi che implementano l'interfaccia. Le classi hanno tipi generici. Vorrei clonare da un'istanza di una classe all'altra.C# Generic Copy Constructor

interface IFoo 
{ 
    // stuff 
} 

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

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

Ho un Foo e vorrei un Bar. Bar ha un costruttore di copie che prende un parametro di IFoo. ho creato un metodo di estensione per implementare il clone: ​​

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

chiamata al metodo richiede il tipo:

someFoo.Clone<T> ... 

Esiste un modo di omettere dichiarare il tipo quando si chiama il metodo modificando il metodo di estensione , o in qualsiasi altro modo, per consentire all'istanza di essere semplicemente inoltrata senza preoccuparsi del suo tipo sottostante?

Aggiornamento Ecco come viene utilizzato per illustrare meglio la situazione.

In un metodo, viene ripetuta una raccolta e viene restituita un'enumerazione di IFoo. Nel metodo guardo un attributo della collezione sorgente e determina il tipo di 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; 

Il metodo di chiamata ha un elenco. Successivamente seleziono singoli elementi da questo elenco per l'uso, a quel punto vorrei una barra invece di un pippo. Quando si seleziona dalla lista le istanze sono di tipo IFoo, in quanto vedono solo i metodi di estensione per "questo IFoo foo". Non voglio lanciare IFoo to a Foo, che richiederebbe la re-dichiarazione del tipo di T. Vorrei solo che Foo dica a Bar cosa è. È possibile?

+0

Forse mi manca qualcosa, ma se lo si la tua funzione di estensione prende un IFoo, come si fa a "clonarlo" in una barra se è di tipo Foo? –

+0

Tutto ciò a cui tengo sono i valori delle proprietà IFoo copiate da Foo a Bar. – blu

risposta

0

Se funziona per il tuo scenario potresti avere un IFoo<T>. Inoltre, se non ti dispiace avere specifici metodi di estensione, potresti semplicemente ricevere uno Foo<T>. Hai davvero bisogno di passare qualcosa che faccia riferimento al T in modo che il compilatore possa dedurre il tipo appropriato.

0

Quando è necessario il controllo completo sopra il vostro clone di copia completa, questo modello è molto buono:

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

Definire contructor protetta per la clonazione - classi in modo derivata può clonare valori nella classe base. Questo modello deve essere scritto a mano (o generato con l'aiuto di un buon modello T4) ma è molto buono per la clonazione profonda.

Aggiornamento: Penso di aver frainteso la domanda e ho già implementato la clonazione. Freddy ha ragione: il compilatore deve sapere quale tipo deve dedurre e non può farlo dal tipo IFoo. Può farlo in (questo Foo < T> foo) però.

0

Prova definendo il metodo come tale

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

In questo modo, il parametro avrebbe un tipo generico e il compilatore avrebbe una fonte per dedurre il tipo da.

2

modo da avere tutto ok, ma si vuole essere in grado di utilizzare la sintassi

someFoo.Clone() 

invece di

someFoo.Clone<int>() 

si desidera che l'int essere implicito, piuttosto che dover mettere ther esplicitamente ?

Il motivo per cui non è possibile farlo nell'esempio di codice è che IFoo non fa riferimento al tipo generico T necessario per creare Bar<T>.

Vorrei suggerire che si ha realmente bisogno di un'altra interfaccia: IFoo<T>

Se tu avessi quello, e il metodo di estensione simile a questa:

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

Allora non avrete nessun problema utilizzando

IFoo<int> someFoo = new Foo<int>(); 
Bar<int> someBar = someFoo.Clone(); 

Speranza che aiuti