Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 强制父类方法调用重写的方法而不是子重写_C#_Inheritance_Overriding - Fatal编程技术网

C# 强制父类方法调用重写的方法而不是子重写

C# 强制父类方法调用重写的方法而不是子重写,c#,inheritance,overriding,C#,Inheritance,Overriding,在C2中我能做些什么,当C2.A调用B时,下一个调用是C1.A,而不是C2.A,这会导致无限递归?IRC上的一位帮助人员提供了这个黑客式的非线程安全解决方案: public class C1 { public virtual void A() { Console.WriteLine("Good"); } public void B() { A(); } // <-- wrong A when when called in child classes :( } public

在C2中我能做些什么,当C2.A调用B时,下一个调用是C1.A,而不是C2.A,这会导致无限递归?

IRC上的一位帮助人员提供了这个黑客式的非线程安全解决方案:

public class C1 {
    public virtual void A() { Console.WriteLine("Good"); }
    public void B() { A(); } // <-- wrong A when when called in child classes :(
}
public class C2 : C1 {
    public override void A() { B(); }
}

我不得不重新命名你的类和方法——As、Bs和Cs快把我逼疯了

注意:这是一个重做,在您的注释中指出基类必须单独处理之后。我想这回答了你的问题。这很粗糙,但我认为应该有用:

public class C1 {
    public virtual void A() { Console.WriteLine("Good"); }
    public void B() { A(); }
}
public class C2 : C1 {
    bool _aOnCallStack = false;
    public override void A() { 
        if (!_aOnCallStack) {
            _aOnCallStack = true;
            B(); 
        }
        else {
            base.A();
            _aOnCallStack = false;
        }
    }
}
然后,在我的主函数中,我有如下代码:

public class Base {
    public virtual void TheVirtualFunction() {
        Console.WriteLine($"Base Class Implemenation of Virtual Function from type {GetType().Name}");
    }
    public void NonVirtualFuction() {
        Console.WriteLine($"The non-Virtual Function - Calling Vitual function now from type {GetType().Name}");
        TheVirtualFunction();
    }
}

public class Sub : Base
{
    private bool _isCallingAgain = false;
    public override void TheVirtualFunction()
    {
        Console.WriteLine($"Sub Class Implemenation of Virtual Function from type {GetType().Name}");
        if (_isCallingAgain)
        {
            Console.WriteLine($"Skipping because v-func called twice from type {GetType().Name}");
            return;
        }
        _isCallingAgain = true;
        Console.WriteLine($"This pass through the virtual function does something (from type {GetType().Name})");
        NonVirtualFuction();
        _isCallingAgain = false;
    }
}
所有这些喷涌到控制台的结果:

static void Main(string[] args) {
    var theBase = new Base();
    Console.WriteLine("Calling Base Class Non Virtual function");
    theBase.NonVirtualFuction();

    Console.WriteLine("\r\nCalling Base Class Virtual function directly");
    theBase.TheVirtualFunction();

    var theSub = new Sub();
    Console.WriteLine("\r\nCalling Non-Virtual Function (implemented in the base class) using sub-class reference");
    theSub.NonVirtualFuction();

    Console.WriteLine("\r\nCalling Sub Class Virtual function directly");
    theSub.TheVirtualFunction();

    Console.ReadLine();
}
请注意,它调用子类虚函数两次,但一个保护位阻止它在第二次执行任何操作。这差不多就是你想出来的,但我是独立完成的

保护位_isCallingAgain是一个私有实例成员变量。它必须在单个执行线程上访问。执行路径进入Sub的v-func,进入Base的非虚函数,然后再次返回Sub的v-func。除了确保它是私有的之外,没有必要用锁或其他东西来保护它


我认为这是你唯一的选择。像这样的不可重入保护是一种非常常见的模式,这在我进行MFC和Win32 Windows UI编程时非常常见。

这难道还不够吗?将A的实现移动到基类中一个单独的私有方法中,然后从基类调用它

Calling Base Class Non Virtual function
The non-Virtual Function - Calling Vitual function now from type Base
Base Class Implemenation of Virtual Function from type Base

Calling Base Class Virtual function directly
Base Class Implemenation of Virtual Function from type Base

Calling Non-Virtual Function (implemented in the base class) using sub-class reference
The non-Virtual Function - Calling Vitual function now from type Sub
Sub Class Implemenation of Virtual Function from type Sub
This pass through the virtual function does something (from type Sub)
The non-Virtual Function - Calling Vitual function now from type Sub
Sub Class Implemenation of Virtual Function from type Sub
Skipping because v-func called twice from type Sub

Calling Sub Class Virtual function directly
Sub Class Implemenation of Virtual Function from type Sub
This pass through the virtual function does something (from type Sub)
The non-Virtual Function - Calling Vitual function now from type Sub
Sub Class Implemenation of Virtual Function from type Sub
Skipping because v-func called twice from type Sub

知道你完全处于黑客模式有帮助。与其他建议相比,这种黑客可能在更多的场景中起作用。但是它慢了很多。此实现尝试尽可能通用。但是,如果只想解决这个特定的示例,您可能只需要在适当的硬编码索引处获取帧&检查/比较声明类型

public class C1 {
    private void AImplementation() { Console.WriteLine("Good"); }
    public virtual void A() { AImplementation(); }
    public void B() { AImplementation(); }
}
public class C2 : C1 {
    public override void A() { B(); }
}
或者,就像我说的,你可以检查一下

public class C1 {
    public virtual void A() { Console.WriteLine("Good"); }
    public void B() { A(); }
}
public class C2 : C1 {
    public override void A()
    {
        var method = new System.Diagnostics.StackTrace()
                    .GetFrames().Skip(1).Select(f => f.GetMethod())
                    .FirstOrDefault(m => m.Name == nameof(A) && m.DeclaringType == typeof(C2));
        if (method == null) B();
        else base.A();
    }
}

正如其他人所说,这是一个糟糕的解决方案,如果可以的话,您可以用更好的设计来解决。

您不能随心所欲,因为覆盖不是这样工作的。为什么你要从覆盖A中调用B?对我来说,这似乎只是一个错误的设计。我知道的唯一方法是,C1.B和C1.A都应该称为私人C1.PrivateA。看来你必须重新考虑你的设计。这个黑客的可能复制可能会帮助你,但这不会解决糟糕的设计,我无法想象你为什么需要这样的设计。当C1.B需要调用特定的a方法时,不应重写此方法。当C1.B方法应该调用相应的被重写方法时,被重写的C2.A不应该调用C1.B来创建递归。C2.A需要完成C1.B已经完成的所有事情。不调用它将涉及大量不必要的代码复制。@Sparr也许您可以提供一个更现实的场景?我真的想不出你为什么需要这样做的原因。@spar这可能是真的,那么你应该创建一个C1.PrivateA或C1.ProtectedA,它将从C1.B和C1.a调用,并且没有递归问题。问题是,C1.B需要调用任意一个.A,任意一个.A调用C1.B,这导致了递归。您只需分离相同的部分,例如受保护函数的受保护C1.common,这将从C1.many和C2.one调用。感谢您让我意识到我在问题中没有指定我正在寻找一个可以在子类定义中实现的解决方案。@Sparr:我重新编写了代码。我相信我的基层是你们基层的反映。我的小班做所有的奇怪的工作来满足你的需要。我想,但我不确定它是否能满足你的要求。如果没有,它可能会被修改以使其工作。该死,我刚刚意识到它基本上与您的代码相同。但是,它有点不同,你的代码更简单,我认为我的代码更清晰。无论如何。。。祝你好运.re lock,如果两个不同的线程同时调用同一个实例的方法会发生什么?好吧,是的,那么你需要一个锁来实现这一点,但我需要C2中的一个解决方案。如果你直接调用B,那也应该调用C1.a吗?
var method = new System.Diagnostics.StackTrace().GetFrame(2).GetMethod();
if (method.Name != nameof(A)) B();
else base.A();