new 修饰符
使用 new 修饰符显式隐藏从基类继承的成员。若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。
请看下面的类:
public class MyBaseC 
{
   public int x;
   public void Invoke() {}
}
在派生类中用 Invoke 名称声明成员会隐藏基类中的 Invoke 方法,即:
public class MyDerivedC : MyBaseC
{
   new public void Invoke() {}
}
但是,因为字段 x 不是通过类似名隐藏的,所以不会影响该字段。
通过继承隐藏名称采用下列形式之一: 
引入类或结构中的常数、指定、属性或类型隐藏具有相同名称的所有基类成员。 
引入类或结构中的方法隐藏基类中具有相同名称的属性、字段和类型。同时也隐藏具有相同签名的所有基类方法。有关更多信息,请参见 3.6 签名和重载。 
引入类或结构中的索引器将隐藏具有相同名称的所有基类索引器。 
在同一成员上同时使用 new 和 override 是错误的。
在不隐藏继承成员的声明中使用 new 修饰符将生成警告。
有关隐藏名称的更多信息,请参见 3.7.1 名称隐藏。
有关完全限定名的更多信息,请参见 3.8.1 完全限定名。
示例
在该例中,基类 MyBaseC 和派生类 MyDerivedC 使用相同的字段名 x,从而隐藏了继承字段的值。该例说明了 new 修饰符的使用。同时也说明了如何使用完全限定名访问基类的隐藏成员。
// cs_modifier_new.cs
// The new modifier
using System;
public class MyBaseC 
{
   public static int x = 55;
   public static int y = 22;
}public class MyDerivedC : MyBaseC 
{
   new public static int x = 100;   // Name hiding
   public static void Main() 
   {
      // Display the overlapping value of x:
      Console.WriteLine(x);      // Access the hidden value of x:
      Console.WriteLine(MyBaseC.x);      // Display the unhidden member y:
      Console.WriteLine(y);
   }
}
输出
100
55
22
如果移除 new 修饰符,程序将继续编译和运行,但您会收到以下警告:
The keyword new is required on 'MyDerivedC.x' because it hides inherited member 'MyBaseC.x'.
如果嵌套类型正在隐藏另一种类型,如下例所示,也可以使用 new 修饰符修改此嵌套类型。
示例
在该例中,嵌套类 MyClass 隐藏了基类中具有相同名称的类。该例不仅说明了如何使用完全限定名访问隐藏类成员,同时也说明了如何使用 new 修饰符消除警告消息。
// cs_modifer_new_nested.cs
// Using the new modifier with nested types
using System;
public class MyBaseC 
{
   public class MyClass 
   {
      public int x = 200;
      public int y;
   }
}public class MyDerivedC : MyBaseC 
{
   new public class MyClass   // nested type hiding the base type members
   {
      public int x = 100;
      public int y; 
      public int z;
   }   public static void Main() 
   {
      // Creating object from the overlapping class:
      MyClass S1  = new MyClass();      // Creating object from the hidden class:
      MyBaseC.MyClass S2 = new MyBaseC.MyClass();      Console.WriteLine(S1.x);
      Console.WriteLine(S2.x);   
   }
}
输出
100
200

解决方案 »

  1.   

    调用了刚定义的doit(a aa) 方法
      

  2.   

    b就是a???b是a 的继承类啊,当把b传入doit方法的时候,不是会根据运行期类型自动调用相应的方法的吗?也就是说应该调用b的方法啊
      

  3.   

    那是因为new的缘故,如果你改用override就应该是b.play
      

  4.   

    doit(a aa)中的参数是class a的实例,在运行时调用a.play方法,b:a,如果a的paly方法是abstact or virtual,并且 b 有override paly,则调用b.play ,
    如果doit(a aa)是这样的doit(b aa)则也执行子类的方法b.play
      

  5.   

    不是的。
    举个例子,大家都知道System.Object是所有类的基类,任何一个派生类如果要转化为Object后,你认为Object能知道他的派生类应该做什么事吗
    Object o;
    string s="abc";
    o=s;
    //难道能这样用吗:o.substring(...)
    //因为在这里进行了隐式转换
      

  6.   

    new 只是隐藏了基类的方法,而不是 override 。你在实例化扩展类的同时,基类也包含其中。当然可以调用基类的方法啦
      

  7.   

    因为是通过public void doit(a aa)
    调用的
    所以
    只能执行a的方法
    想要执行b的方法要用virtual方法
    virtual是靠运行时的实际类型来决定执行方法的
      

  8.   

    To zjsen(星愿) :
    ------------------------------------
    不是的。
    举个例子,大家都知道System.Object是所有类的基类,任何一个派生类如果要转化为Object后,你认为Object能知道他的派生类应该做什么事吗
    Object o;
    string s="abc";
    o=s;
    //难道能这样用吗:o.substring(...)
    //因为在这里进行了隐式转换
    -------------------------------------------
    这样肯定连编译都不会通过的,而且我的doit方法参数是a 也就是你这里说的 o,那么方法里面当然只能使用o的方法了,其实就是向上转型了,这样是安全的。
      

  9.   

    当你从子类中写一个与父类中某个方法同名时 又不想覆盖父类的方法就要用new
    new告诉编译器 这个方法不覆盖父类方法
    所以说用new隐藏继承成员
      

  10.   

    是不是说,如果想覆盖父类的方法,那么父类的方法就一定要声明成virtual啊?
      

  11.   

    问题解决了,谢谢各位的帮助,又让我对oo,对c#有了更深入地了解