2012-04-16 3 views
8

Пусть у меня есть два класса:Cast базовый экземпляр для производного класса (опущенными) в C#

class Employee 

и

class AdvancedEmployee:Employee 

Я знаю, что-то вроде этого не будет работать, так как я не могу downcast на C#:

var employee = new Employee(); 
var advanced = employee as AdvancedEmployee; 

Мой вопрос: Как эффективно выполнить downcast? На самом деле у меня есть конструктор в AdvancedEmployee, который принимает параметр Employee как параметр и использует его для ввода своих значений, в основном делая клон.


Update

Для решения данных, которые будут получать дублируются я изменил подход немного и теперь AdvancedEmployee СОДЕРЖИТ работник вместо того, чтобы один сам. Пример:

class Employee; 

class AdvancedEmployee 
{ 
    private employee 

    public AdvancedEmployee(Employee employee){ 

    this.employee = employee 

    }   

} 
+2

Сделать оба совместимыми с интерфейсом, IEmployee? – SpaceBison

+0

Я не могу изменить Employee. –

+0

@IsraelLot, вы, безусловно, можете подавить на C#. Я подозреваю, что вам просто не хватает синтаксиса: «AdvancedEmployee advanced = (AdvancedEmployee) сотрудник». Конечно, это даст ошибку во время выполнения, если ссылочный объект на самом деле не является экземпляром AdvancedEmployee. – Ben

ответ

3

Это не может быть литая, это на самом деле Convertion между различными типами.

Я бы добавил функцию ctor или статического члена, такую ​​как AdvancedEmployee FromBase(Employee e), до Конструкция производного типа от данного базового типа.

+0

@downvoter: помочь объяснить? – Tigran

1

as in C# проверяет на наличие тип исполнения. То есть, если тестируемый объект действительно не является AdvancedEmployee, вы не сделаете его магически конвертированным Employee в AdvancedEmployee. Поэтому, если вам нужен AdvancedEmployee, вам нужно как-то построить его.

Существуют разные подходы в зависимости от того, что вы собираетесь достичь. Возможно, вы можете сделать с конструктором AdvancedEmployee(Employee proto), который скопирует необходимые значения из proto? Или, может быть, вам нужно обернуть существующий EmployeeAdvancedEmployee.

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

Путь к успеху (с некоторым вкусом Java) может заключаться в создании фабрики Employee, которая при необходимости создала бы AdvancedEmployee. Затем вам нужно сделать весь код, используя завод вместо того, чтобы создать Employee с new. Этот сценарий, однако, не поможет, если вам все равно потребуется изменить тип выполнения.

+0

Вот что я сейчас делаю. Мне было интересно, был ли причудливый способ. –

+2

Не совсем. Существуют и другие языки OO, где вы можете изменить _runtime type_ объекта на лету - но не на C#/Java/C++. в C# вы можете создать только объект _new_. – Vlad

+0

@downvoter: помочь объяснить? – Vlad

2

Создание нового объекта является наиболее читаемым и ясным способом. Вы также можете определить явные или неявные операторы преобразования типов в вашем классе Employee.

public static explicit operator AdvancedEmployee(Employee e) 
{ 
    return new AdvancedEmployee(e); 
} 

И затем использовать его как это:

var e = new Employee(); 
var ae = (AdvancedEmployee) e; 
+0

Поскольку OP не может изменять 'Employee', он также не может определять явные или неявные операторы преобразования типов внутри него. – comecme

4

Создайте интерфейс.И так как вы не можете изменить Работник, создать adapter, что у вас есть:

class EmployeeAdapter : IEmployee 
{ 
    private Employee emp; 
    public EmployeeAdapter(Employee emp) { this.emp = emp; } 
    public int SomeMethodInEmployee() { return emp.SomeMethodInEmployee(); } 
} 

class AdvancedEmployee : IEmployee { } 
+0

@downvoter: помочь объяснить? –

+0

Нижняя часть - это моя ошибка. Я неправильно понял вопрос. К сожалению, какая-то неудача означает, что я не могу отменить свой голос, теперь я понимаю, что ошибся. – Ben

+1

Оказывается, если вы отредактируете сообщение (даже добавив одно место), вы сможете вернуть свой голос. – Ben

2

Вот так я обработал его в прошлом, которые я думал, был круто ... если все элементы данных в Employee и AdvancedEmployee являются свойствами, то вы можете использовать отражение, чтобы скопировать значения данных из базового класса в производный класс. Затем вы можете работать с производным классом, как если бы он был изначально напечатан таким образом, без необходимости инкапсулировать базовый класс.

public class Employee 
{ 
    public int ID { get; set; } 
    public string Foo { get; set; } 

    public void SomeMethod() { } 
} 

public class AdvancedEmployee : Employee 
{ 
    public string Bar { get; set; } 

    public void SomeAdvMethod() { } 
} 

Employee emp = new Employee() { ID = 5, Foo = "Hello" }; 

// To create a AdvancedEmployee from emp 
AdvancedEmployee advEmp = new AdvancedEmployee() { Bar = "A prop not in Emp that might need a value" } 
foreach (var p in typeof(Employee).GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.CanWrite)) 
    typeof(AdvancedEmployee).GetProperty(p.Name).SetValue(advEmp, p.GetValue(emp)); 

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

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