C# 强制方法从基调用子类new方法

C# 强制方法从基调用子类new方法,c#,class,methods,public,protected,C#,Class,Methods,Public,Protected,我的理解是,子类的行为与父类完全相同,除了附加的方法或那些使用new和override关键字“重写”的方法。显然,这是不对的 请参阅下面的代码(为便于阅读,删除括号) 我已经知道,我可以用new关键字将BIG.Output(string)隐藏为小写。直接打电话时,效果非常好 >> foo.Output("Outputting...") SMALL - Outputting... 这与我的理解有冲突。我认为定义类SMALL:BIG与定义类SMALL并从BIG复制粘贴所有方法完全一样。

我的理解是,子类的行为与父类完全相同,除了附加的方法或那些使用
new
override
关键字“重写”的方法。显然,这是不对的

请参阅下面的代码(为便于阅读,删除括号)

我已经知道,我可以用
new
关键字将
BIG.Output(string)
隐藏为小写。直接打电话时,效果非常好

>> foo.Output("Outputting...")
SMALL - Outputting...
这与我的理解有冲突。我认为定义
类SMALL:BIG
与定义
类SMALL
并从BIG复制粘贴所有方法完全一样。简言之,我认为上面的小班相当于:

class SMALL
    public void Output(string text = "")
        Console.WriteLine("SMALL - " + text);

    public void CallingOutput()
        Output("Outputting...");
显然这是不正确的,因为

>> foo.CallingOutput()
BIG - Outputting...
当间接调用时,它仍然使用来自
BIG
的原始
输出(字符串)

正确的方法是什么,以便
foo.CallingOutput()
输出

“小-输出…”

假设我没有访问
BIG
的权限,并且不允许进行任何更改。我不想隐藏
CallingOutput()
,因为这基本上是重写类。 (是的,隐藏
CallingOutput()
可以让它工作)

在发布这篇文章之前,我做了一些搜索,在
C++
中发现了一个类似的问题。然而,答案是不可能的

  • 我不相信。这是一种功能强大的语言,但却无法告诉编译器哪种方法是哪种方法
  • 这是一种不同的语言,所以这篇文章是允许的,因为它不能被认为是重复的

  • 将关键字
    new
    替换为
    override
    ,如下所示:

    class SMALL:BIG
    public override void Output(string text = "")
        Console.WriteLine("SMALL - " + text);
    
    创建一个垫片 不能修改或重写现有类中的任何内容,除非它被设计为被重写。这是故意的

    也就是说,您可以创建一个新的“shim”(pass-through)类,该类与原始类完全相同,但其成员被声明为virtual。这是通过使用
    new
    virtual
    修饰符来实现的

    拥有shim类后,可以根据法线重写该方法。例如:

    class Big
    {
        public void Output(string text) { Console.WriteLine("Big - {0}", text); }
    
        public void CallingOutput()
        {
            Output("Outputting...");
        }
    }
    
    class Shim : Big
    {
        public new virtual void Output(string text) { base.Output(text); }
    
        public void CallingOutput()
        {
            Output("Outputting...");
        }
    }
    
    现在您有了一个Shim类,它将允许您想要的内容。因此,将其分为子类(而不是大类)并查看会发生什么:

    class Small : Shim
    {
        public override void Output(string text) { Console.WriteLine("Small - {0}", text); }
    }
    
    测试它:

    Shim s = new Shim();
    s.CallingOutput();   //Original behavior
    
    Shim s = new Small();
    s.CallingOutput();   //Overridden behavior
    
    输出:

    Big - Outputting...
    Small - Outputting...
    

    在基类中声明方法
    virtual
    ,在child中声明方法
    override
    ,然后基类将对其进行装箱,
    new
    按设计不起作用是的,
    override
    new
    是不可互换的。它们有不同的效果。通过显示您对
    foo
    的使用,您的问题可以变得更清楚;
    foo
    的类型和对象创建。@abatishchev如上所述,我不允许对BIG进行更改。然后不要继承它。它不是为继承而设计的。相反,你可以使用构图。创建一个小类来引用一个大对象,并根据需要使用它。不会在所有情况下都有效,但可能会让你达到你需要的目的?那么这是通过设计:你尝试攻击大(通过覆盖非虚拟的内容来改变其行为),而框架不允许你这样做(新的只在同一类型的范围内工作),因为这不是设计和预期的大,抱歉。但是,请看@itsme86的答案-这是正确的方法(但并不总是适用)我不能对
    BIG
    BIG进行更改。Output()
    未标记为虚拟、抽象或重写,因此我不能这样做。在基类中执行此操作您所说的基类是什么意思?大不是基本阶级吗?是的!读了这篇文章你就会明白我不明白。我在问题和评论中说了两次,我不允许对基类进行更改。它是原样的,并且没有标记为虚拟、抽象或覆盖,因此我不能使用
    override
    关键字。不,这不是我想要的。目标是让
    CallingOutput
    SMALL
    中调用
    输出。在我的问题中,我已经实现了您在示例中所做的,甚至没有使用
    Shim
    类。请再检查一遍!正如我所说,你不能拥有你想要的东西,这是故意的。在我的示例中,可以使用
    垫片
    而不是大垫片。这与您已经做的不同,因为Small中的覆盖实际上是有效的。我将更新示例代码。正如我在问题中所述,我不想“重写”
    CallingOutput
    ,因为这基本上是重写
    BIG
    。是的,你是对的,它不应该被覆盖,如果它最初不是被设计成这样的,我理解。对不起,你不能得到你想要的。我建议使用shim比重写BIG要省力,因为您仍然可以访问
    this
    ,仍然可以访问受保护的成员,仍然可以将实例存储在
    IEnumerable
    中,或者将其作为参数传递给需要使用
    BIG
    的地方,等等。尽管如此,您还是可以调用它。
    Big - Outputting...
    Small - Outputting...