【问题标题】:Static method return an object of it's containing class type静态方法返回一个包含类类型的对象
【发布时间】:2013-07-31 20:16:59
【问题描述】:

我有:

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 方法,使其返回一个学生而不是一个人。 将一个人投射给学生会给我一个错误

【问题讨论】:

    标签: c# inheritance polymorphism


    【解决方案1】:

    你不能。不能在子类中重写静态方法,并且无法区分 Student.GenerateRandomInstancePerson.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;
    }
    

    当然,如果指定的类型不包含合适的构造函数,这也会失败。

    【讨论】:

    • +1 谢谢! person 构造函数虽然有 2 个参数......我应该提一下,我不知道你会在哪里发布这个不错的答案;)
    • @TonoNam 对于Person 的每个子类型,参数是否都相同,或者它们可能是不同的类型?
    • 我正在编辑一个将在不到 1 分钟的时间内完成的编辑,非常感谢您的帮助...
    • Person 需要两个参数,这就是为什么我不能使用 new 关键字:(
    • p.s.w.g 很好,我不必指定T 我知道T 必须是父类类型。我没有办法删除它吗?因为我不能使用this 关键字,我怎么知道类型才能删除&lt;T&gt; 泛型参数。
    【解决方案2】:

    试试这样的。 PersonStudent 各自定义了自己的 GenerateRandomInstanceRandomizeProperties 方法。 Student 调用PersonRandomizeProperties 让基类随机化它知道的属性。然后Student 只会随机化Student 类引入的属性。

    注意:这个问题通常由Abstract FactoryBuilder 设计模式解决。下面的解决方案都不是。

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

    【讨论】:

      【解决方案3】:

      您需要在 Student 类中覆盖 GenerateRandomInstance() 方法。目前正在调用 Person 中的基本方法。

      【讨论】:

      • 你不能覆盖静态方法
      猜你喜欢
      • 2019-02-03
      • 1970-01-01
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 2023-03-20
      • 2012-06-09
      相关资源
      最近更新 更多