C# 什么是阴影?

C# 什么是阴影?,c#,polymorphism,shadowing,C#,Polymorphism,Shadowing,在C#中,“阴影”一词是什么意思?我读过,但没有完全理解。 重写:在基类上重新定义现有方法 阴影:创建一个与基类中的方法具有相同签名的全新方法 这里有一个关于阴影的问题。语言示例是用VisualBasic编写的(遗憾的是,MSDN上没有等效的C#页),但它通常涉及概念,希望能帮助您理解 编辑:似乎有一个关于阴影的问题,只是它被称为隐藏在C#中。此外,还提供了一个很好的概述。假设我有一个实现虚拟方法的基类: public class A { public virtual void M()

在C#中,“阴影”一词是什么意思?我读过,但没有完全理解。

  • 重写:在基类上重新定义现有方法
  • 阴影:创建一个与基类中的方法具有相同签名的全新方法
    • 这里有一个关于阴影的问题。语言示例是用VisualBasic编写的(遗憾的是,MSDN上没有等效的C#页),但它通常涉及概念,希望能帮助您理解


      编辑:似乎有一个关于阴影的问题,只是它被称为隐藏在C#中。此外,还提供了一个很好的概述。

      假设我有一个实现虚拟方法的基类:

      public class A
      {
          public virtual void M() { Console.WriteLine("In A.M()."); }
      }
      
      我还有一个派生类,它也定义了一个方法M:

      public class B : A
      {
          // could be either "new" or "override", "new" is default
          public void M() { Console.WriteLine("In B.M()."); }
      }
      
      现在,假设我写了一个这样的程序:

      A alpha = new B(); // it's really a B but I cast it to an A
      alpha.M();
      
      我有两种不同的选择来实现我的目标。默认行为是调用A的M版本。(这与将“
      new
      ”关键字应用于
      B.M()
      时的行为相同)

      当我们有一个名称相同但从基类调用时行为不同的方法时,这称为“阴影”


      或者,我们可以在
      B.M()
      上指定“
      override
      ”。在这种情况下,
      alpha.M()
      将调用B的M版本。

      阴影隐藏基类中的方法。使用您链接的问题中的示例:

      class A 
      {
         public int Foo(){ return 5;}
         public virtual int Bar(){return 5;}
      }
      class B : A
      {
         public new int Foo() { return 1;}
         public override int Bar() {return 1;}
      }
      
      B
      重写虚拟方法
      Bar
      。它隐藏(阴影)非虚拟方法
      Foo
      。Override使用Override关键字。阴影是用new关键字完成的

      在上面的代码中,如果在类
      B
      中定义
      Foo
      方法时未使用new关键字,则会得到以下编译器警告:

      'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
      

      我不会担心理解或实现阴影,除非它“非常适合”问题。我见过它使用不当,导致奇怪的逻辑错误的次数比正确使用要多得多。我认为,最大的原因是,当程序员忘记在方法签名中放置覆盖时,编译器警告将建议使用新关键字。我一直认为应该建议使用重写。

      隐藏是指在子类中隐藏具有新定义的基类方法

      隐藏和重写之间的区别与调用方法的方式有关

      这样,当重写虚拟方法时,基类的方法调用表的调用地址将替换为子例程的地址

      另一方面,当一个方法被隐藏时,一个新地址被添加到子类的方法调用表中

      调用所讨论的方法时:

    • 获取方法调用表类类型,如果调用时引用基类,则获取基类方法表,如果引用子类,则获取子类方法表
    • 在表中搜索该方法,如果找到该方法,则进行调用,否则搜索基类方法表
    • 如果调用方法时引用了子类,则行为是相同的,如果方法已被重写,则将在基类中找到方法地址,如果方法被隐藏,则将在子类上找到方法地址,并且由于已找到,因此不会搜索基类表

      如果调用方法时引用基类,则行为会发生变化。重写时,当方法地址覆盖基类条目时,我们将调用子方法,即使在持有对基类的引用时也是如此。通过阴影,基类方法表(在我们持有对基类的引用时,它是唯一可见的)包含虚拟方法地址,因此,基类方法将被调用


      一般来说,阴影是一个坏主意,因为它会根据我们对实例的引用,在实例的行为上引入差异。

      扩展Kent的正确答案

      在消除何时调用哪个方法的歧义时,我喜欢考虑使用以下方法进行隐藏与重写

      • 阴影:调用的方法取决于调用点的引用类型
      • 重写:调用的方法取决于调用点的对象类型
      输出:

      十,
      20

      如果要隐藏基类方法,请在Base中使用override[virtual method in Base]

      如果要隐藏子类方法,请使用new in base[non-irtual method in base]->shadow

      Base B=new Child()
      
      B.VirtualMethod()
      ->调用子类方法


      B.NonVirtualMethod()
      ->调用基类方法

      重写:实现相同的名称和完全相同的参数 不同的子类

      • 若将其视为派生类或基类,则使用派生方法
      阴影:相同的名称和完全相同的参数,在子类中以不同的方式实现

      • 若将其视为DerivedClass,则使用派生方法
      • 如果将其视为基类,则使用基类方法

        • 希望这个简短的解释能有所帮助。

          阴影
          -替换父类的完整元素

          class InventoryAndSales
          {
              public int InvoiceNumber { get; set; }
          }
          
          //if someone calls for this class then the InvoiceNumber type is now object 
          class NewInventoryAndSales : InventoryAndSales
          {
              public new object InvoiceNumber { get; set; }
          }
          


          重写
          -仅替换实现。它不替换它不替换的数据类型,例如,您有一个变量,它不会将其转换为方法,因此如果有方法,它将使用该方法,并且只更改了实现

           class InventoryAndSales
              {
                  public virtual int GetTotalSales(int a, int b)
                  {
                      return a + b;
                  }
              }
          
          
              class NewInventoryAndSales : InventoryAndSales
              {
                  //it replaces the implementation in parent class
                  public override int GetTotalSales(int a, int b)
                  {
                      return a * b;
                  }
              }
          

          不是每个人都以完全相同的方式解释事情,是吗?学校里不是有一些老师你认为哪里比其他老师好吗?应该注意的是,阴影是一种
           class InventoryAndSales
              {
                  public virtual int GetTotalSales(int a, int b)
                  {
                      return a + b;
                  }
              }
          
          
              class NewInventoryAndSales : InventoryAndSales
              {
                  //it replaces the implementation in parent class
                  public override int GetTotalSales(int a, int b)
                  {
                      return a * b;
                  }
              }