2009-02-18 4 views
5

У меня есть интерфейс и два класса, которые реализуют интерфейс. Классы имеют общие типы. Я хотел бы клонировать от экземпляра одного класса к другому.C# Generic Copy Constructor

interface IFoo 
{ 
    // stuff 
} 

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

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

У меня есть Foo и вам понравится бар. В баре есть экземпляр-копия с параметром 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; 

Метод вызова имеет список. Позже я выбираю отдельные элементы из этого списка для использования, и в этот момент мне нужна панель вместо Foo. При выборе из списка экземпляры имеют тип IFoo, так как в них видны только методы расширения для «this IFoo foo». Я не хочу передавать IFoo в Foo, что потребует повторного объявления типа T. Я бы просто хотел, чтобы Foo сказал Bar, что это такое. Это возможно?

+0

Возможно, мне что-то не хватает, но если вы Функция расширения ur принимает IFoo, как она должна «клонировать» ее в панель, если она имеет тип Foo? –

+0

Все, о чем я забочусь, это значения в свойствах IFoo, которые копируются из Foo в Bar. – blu

ответ

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), но очень хорош для глубокого клонирования.

Обновление: Я думаю, что я неправильно понял вопрос и уже выполнил клонирование. Freddy прав - компилятор должен знать, к какому типу он должен делать вывод, и он не может это сделать из типа IFoo. Он может сделать это в (это Foo < T> foo).

0

Попробуйте определить метод как таковой

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

Таким образом, параметр будет иметь общий тип и компилятор будет иметь источник выводя типа с.

2

Так у вас есть все в порядке, но вы хотите, чтобы иметь возможность использовать синтаксис

someFoo.Clone() 

вместо

someFoo.Clone<int>() 

вы хотите Int подразумеваться вместо того, чтобы положить его þér явно ?

Причина, по которой вы не можете сделать это в своем примере кода, заключается в том, что 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(); 

Надеюсь, что поможет

 Смежные вопросы

  • Нет связанных вопросов^_^