2009-08-07 3 views
0

В основном моя установка такова:Возможно ли иметь базовый класс с типом возвращаемого значения, который будет соответствовать типу базового класса?

public abstract class BaseObject{ 
    public abstract BaseObject Clone(); 
} 

public class DerivedObject : BaseObject{ 
    public DerivedObject Clone() 
    { 
     //Clone logic 
    } 
} 

Приведенный выше код не компилируется, потому что это не возможно изменить тип возвращаемого при переопределении метода.

Можно ли достичь того, что метод Clone каждого производного типа возвращает аргумент своего собственного типа (может быть, через generics)?

ответ

3

Ну, C# не позволяет ковариантные возвращаемые типы, как вы нашли ... но вы можете дженерики использование:

public abstract class BaseObject<T> where T : BaseObject<T> 
{ 
    public abstract T Clone(); 
} 

public class DerivedObject : BaseObject<DerivedObject> 
{ 
    public override DerivedObject Clone() 
    { 
     // ... 
    } 
} 

Это решение может быть боль различными способами - не в последнюю очередь потому, что это трудно понять, но во многих ситуациях он может работать достаточно хорошо.

EDIT: Причина, по которой я включил ограничение на T, заключается в том, что BaseObject может называть «свои» методы в случаях T, что обычно очень удобно. Если вам это не нужно, вы можете потерять ограничение.

+0

Не могли бы вы описать некоторые из способов, которыми это решение может быть болью? Я пытаюсь выяснить, стоит ли брать эту боль за меньшую боль, не имея при себе всякого типа, когда я использую метод Clone. – chrischu

+0

@Mehrdad: Исправлено, спасибо. @crischu: Ну, нечего сказать, что другой класс не может быть получен из «BaseObject » для одной вещи, поэтому он не является надежным. Также, если вам нужно взаимодействовать с другим типом, он может получить * действительно * волосатый - в буферах протоколов у меня есть «IMessage , где TMessage: IMessage , где TBuilder: IBuilder 'например. Насти. Это в основном нормально, но вам нужно держать прохладную голову. –

0

Вы можете сделать что-то вроде этого. Вместо того, чтобы возвращать значение по умолчанию (T), верните что-то, основанное на логике клонирования.

public class MyBase<T> 
{ 
    public T Clone() 
    { 
     return default(T); 
    } 
} 

public class MyDerived : MyBase<MyDerived> 
{ 
} 

Кстати, для клонирования объекта Я хотел сериализовать текущий объект в память с использованием двоичного сериалайзера, то десериализация, что память обратно в новый экземпляр.

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