在基类中使用重写属性

时间:2013-08-22 17:51:37

标签: c#

我有以下内容:

class Info
{
    public string str;
};

class CarInfo : Info {}

class InfoContainer
{
    public virtual List<Info> info_list {get; set;}
    public bool is_known(Info inf)
    {
        if (-1 == info_list.FindIndex( i => i.str == inf.str) return false;
        return true;
    }  
}

class CarFleetInfo : InfoContainer
{
     new public List<CarInfo> info_list;
     CarFleetInfo()
     {
         info_list = new List<CarInfo>();
     }
}


Main()
{
    CarInfo c = new CarInfo();
    Info i = new Info();
    c.is_known(i);
}

我没有其他“{1}}继承的”特定信息“类(如Info),以及从CarInfo继承的几个类,这些类都覆盖InfoContainer与其他一些“特定信息”的对象列表。

现在,对info_list的调用引发了一个异常,说c.is_known(i)为空。

6 个答案:

答案 0 :(得分:0)

您的问题是new上的new public List<CarInfo> info_list;关键字。在此上下文中,new表示“忽略我的基类提供的定义(如果有的话),而是使用我自己的定义”。因此,当您设置CarInfo的{​​{1}}时,您设置基础info_list的{​​{1}}。然后,当您尝试访问属于Info的{​​{1}}时,它为空。

修复它的最好方法就是取出info_list的{​​{1}}并简单地使用基类的版本。这是正确的方式,可以执行您在此处尝试执行的操作,但也可以使用其他方法。

答案 1 :(得分:0)

你没有覆盖info_list属性,你正在影响它。

要覆盖该属性,您应该使用override关键字而不是new关键字,然后代码将按预期工作。

当你对属性进行遮蔽时,子类会获得具有相同名称的自己的属性,基类对此一无所知。

答案 2 :(得分:0)

您在一个显式隐藏其基类成员的属性上使用new。使用override无效,因为List<Info>不是List<CarInfo>

相反,请考虑使用泛型:

class Info
{
    public string Foo { get; set; }
}

class CarInfo : Info {}

class InfoContainer<T>
    where T: Info
{
    public List<T> info_list { get; set; }

    public bool is_known(T inf)
    {
        if (-1 == info_list.FindIndex(i => i.Foo == inf.Foo)) return false;
        return true;
    }
}

class CarFleetInfo : InfoContainer<CarInfo>
{
}

答案 3 :(得分:0)

有两个问题:

  1. 你应该覆盖而不是遮蔽
  2. 您无法覆盖具有不同签名的方法

    课程信息     {       public string str;     };

    class CarInfo : Info {}
    
    class InfoContainer
    {
        public virtual List<Info> info_list {get; set;}
        public bool is_known(Info inf)
        {
          if (!info_list.Exists(p => p.str == inf.str)) return false;
          return true;
         }
    }
    
    class CarFleetInfo : InfoContainer
    {
         public override List<Info> info_list { get; set; }
    
         CarFleetInfo()
         {
            info_list = new List<Info>();
         }
    }
    
  3. 您不能公开List<CarInfo>覆盖公开List<Info>

答案 4 :(得分:0)

我认为您无法将List<CarInfo>分配给List<Info>,因此您无法以这种方式覆盖info_list。要解决此问题,您必须使用泛型类,而不是定义如下:

class InfoContainer<T> where T : Info
{
  public virtual List<T> info_list {get; set;}
  public bool is_known(T inf)
  {
   if (-1 == info_list.FindIndex( i => i.str == inf.str) return false;
   return true;
  }
}
class CarFleetInfo<T> : InfoContainer<T> where T : CarInfo
{
  public override List<T> info_list {get;set;}
  public CarFleetInfo(){
    info_list = new List<T>();
  }
}

答案 5 :(得分:-2)

基类的目的是提供将被覆盖的函数和定义。覆盖基类是没有意义的。打破语言可能是一个很好的练习,但一般来说,你在编译器中创建了一个悖论和无限循环。覆盖属性意味着预处理器应该运行代码而不是它的基类操作。

但是,在大多数情况下仍应调用基类操作,以确保实例化并正确初始化继承对象的所有字段和对象。