2013-07-31 3 views
3

у меня есть:статический метод возвращает объект это содержащий класс типа

class Person 
{ 

    public Person(string name, int age) 
    { 
     this.Name = name; 
    } 

    public string Name { get; set; } 

    public virtual void Speak() 
    { 
     Console.Write("Hello I am a person"); 
    } 

    public static T GenerateRandomInstance<T>() where T: Person 
    { 
     var p = new T("hello", 4); // error does not compile 
     // rondomize properties 
     return p;     
    } 
} 

class Student : Person 
{ 
    // constructor I call the base class here 
    public Student(string name, int age) 
     : base(name, age) 
    {  
    } 

    public override void Speak() 
    { 
     Console.Write("Hello I am a student"); 
    } 
} 

Проблема, что у меня есть, что, когда я делаю:

Student.GenerateRandomInstance(); 

Я получаю Person вместо Student. Как я могу исправить метод GenerateRandomInstance, чтобы он возвращал ученика вместо Person. Кастинг человека студенту дает мне ошибку

ответ

5

Вы не можете. Статический метод не может быть переопределен в дочернем классе, и нет возможности различать между Student.GenerateRandomInstance и Person.GenerateRandomInstance — на самом деле они генерируют точно такой же CIL при компиляции.

Вы можете использовать общий метод вместо:

public static T GenerateRandomInstance<T>() where T : Person, new 
{ 
    var p = new T(); 
    // randomize properties 
    return p; 
} 

Person.GenerateRandomInstance<Student>(); 

Но это будет работать только если тип имеет конструктор без параметров. Если вы хотите передать аргументы конструктору, это будет несколько сложнее. Предполагая, что вы всегда знаете, какие ценности вы хотите передать в конструктор вы можете сделать это:

public static T GenerateRandomInstance<T>() where T : Person 
{ 
    var p = (T)Activator.CreateInstance(typeof(T), "hello", 4); 
    // randomize properties 
    return p; 
} 

Конечно, это тоже не сработает, если указанный тип не содержит подходящий конструктор.

+0

+1 спасибо! человек конструктор принимает 2 аргумента, хотя ... Я должен был бы упомянуть, что я не знал вас, где будет опубликовать этот хороший ответ;) –

+0

@TonoNam - это параметры, которые будут одинаковыми для каждого подтипа 'Person' или могут они разные? –

+0

Я работаю над редактированием, которое будет там менее чем за 1 минуту. Большое спасибо за помощь ... –

1

Вам необходимо переопределить метод GenerateRandomInstance() в вашем классе учеников. в настоящее время вызывается базовый метод в Person.

+1

Вы не можете переопределить статический метод –

+0

Ах, справа. Пропустил это. Thanks –

2

Попробуйте что-нибудь подобное. Person и Student каждый определяют свои методы GenerateRandomInstance и RandomizeProperties. Student звонит Person's RandomizeProperties, чтобы базовый класс рандомизировал свойства, о которых он знает. Student будет только рандомизировать свойства, введенные классом Student.

ПРИМЕЧАНИЕ. Эта проблема часто решается с помощью шаблонов проектирования или Builder. Нижеприведенное решение не является ни тем, ни другим.

class Person 
{ 
    public string Name { get; set; } 

    public virtual void Speak() 
    { 
     Console.Write("Hello I am a person"); 
    } 

    public static Person GenerateRandomInstance() 
    { 
     var o = new Person(); 
     RandomizeProperties(o); 
     return o; 
    } 

    protected static void RandomizeProperties(Person o) 
    { 
     // randomize Person properties here 
    } 
} 

class Student : Person 
{ 
    public override void Speak() 
    { 
     Console.Write("Hello I am a student"); 
    } 

    // note the use of the 'new' keyword 
    new public static Student GenerateRandomInstance() 
    { 
     var o = new Student(); 
     RandomizeProperties(o); 
     return o; 
    } 

    protected static void RandomizeProperties(Student o) 
    { 
     Person.RandomizeProperties(o); 

     // randomize Student properties here 
    } 
} 
Смежные вопросы