Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.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# 如何调用base.base.method()?_C#_Polymorphism - Fatal编程技术网

C# 如何调用base.base.method()?

C# 如何调用base.base.method()?,c#,polymorphism,C#,Polymorphism,结果是: 从特殊派生调用。 从派生调用。/*这不是预期的*/ 从基地打来的 如何重写SpecialDrived类,以便不调用中间类“派生”的方法 更新: 我希望从派生类而不是基类继承的原因是派生类包含许多其他实现。既然我不能在这里执行base.base.method(),我想最好的方法是执行以下操作 //无法更改源代码 你不能从C#开始。从IL来看,这实际上是受支持的。您可以对任何父类执行非virt调用。。。但请不要:) 答案(我知道这不是你想要的)是: 事实是,您只能与继承自的类直接交互。将该

结果是:

从特殊派生调用。
从派生调用。/*这不是预期的*/
从基地打来的

如何重写SpecialDrived类,以便不调用中间类“派生”的方法

更新: 我希望从派生类而不是基类继承的原因是派生类包含许多其他实现。既然我不能在这里执行
base.base.method()
,我想最好的方法是执行以下操作

//无法更改源代码

你不能从C#开始。从IL来看,这实际上是受支持的。您可以对任何父类执行非virt调用。。。但请不要:)

答案(我知道这不是你想要的)是:

事实是,您只能与继承自的类直接交互。将该类视为一个层—为其派生类提供尽可能多或尽可能少的功能或其父类的功能

编辑:

您的编辑工作正常,但我想我会使用以下内容:

class SpecialDerived : Base
{
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        base.Say();
    }
}
当然,在实际的实现中,为了扩展性和可维护性,您可能会执行类似的操作:

class Derived : Base
{
    protected bool _useBaseSay = false;

    public override void Say()
    {
        if(this._useBaseSay)
            base.Say();
        else
            Console.WriteLine("Called from Derived");
    }
}

然后,派生类可以适当地控制其父类的状态。

这是一种糟糕的编程实践,在C#中是不允许的。这是一种糟糕的编程实践,因为

  • grandbase的细节是该基地的实施细节;你不应该依赖他们。基类提供了对grandbase的抽象覆盖;您应该使用该抽象,而不是构建旁路来避免它

  • 为了说明前一点的一个具体示例:如果允许,此模式将是另一种使代码容易受到脆弱基类故障影响的方法。假设
    C
    派生自
    B
    ,后者派生自
    A
    C中的代码使用base.base调用a的方法。然后,
    B
    的作者意识到他们在类
    B
    中放了太多的齿轮,更好的方法是使中间类
    B2
    派生自
    a
    ,而
    B
    派生自
    B2
    。在该更改之后,
    C
    中的代码正在调用
    B2
    中的方法,而不是
    a
    ,因为
    C
    的作者假设
    B
    的实现细节,即其直接基类是
    a
    ,永远不会更改。C#中的许多设计决策都是为了降低各种脆性基底失效的可能性;将
    base.base
    定为非法的决定完全可以防止这种特殊的失败模式

  • 您从基础中派生,因为您喜欢它的功能,并且希望重用和扩展它。如果你不喜欢它所做的,并且想围绕它工作,而不是与它一起工作,那么首先为什么你要从它衍生出来?如果您想使用和扩展grandbase的功能,请自己从中派生

  • 出于安全或语义一致性的目的,base可能需要某些不变量,这些不变量由base如何使用grandbase方法的细节来维护。允许基类的派生类跳过维护这些不变量的代码可能会使基类处于不一致、损坏的状态


您还可以在一级派生类中创建一个简单的函数,以便在无法访问派生类源,但需要当前方法之外的所有派生类源的情况下调用grand base function

,然后我建议您也应该执行派生类并调用派生类的实现

以下是一个例子:

class Derived : Base
{
    protected enum Mode
    {
        Standard,
        BaseFunctionality,
        Verbose
        //etc
    }

    protected Mode Mode
    {
        get; set;
    }

    public override void Say()
    {
        if(this.Mode == Mode.BaseFunctionality)
            base.Say();
        else
            Console.WriteLine("Called from Derived");
    }
}

我只想在这里补充一下,因为即使经过很多次,人们仍然会回到这个问题上来。当然,这是一种不好的做法,但(原则上)仍然可以按照作者的意愿:

//No access to the source of the following classes
public class Base
{
     public virtual void method1(){ Console.WriteLine("In Base");}
}
public class Derived : Base
{
     public override void method1(){ Console.WriteLine("In Derived");}
     public void method2(){ Console.WriteLine("Some important method in Derived");}
}

//Here should go your classes
//First do your own derived class
public class MyDerived : Base
{         
}

//Then derive from the derived class 
//and call the bass class implementation via your derived class
public class specialDerived : Derived
{
     public override void method1()
     { 
          MyDerived md = new MyDerived();
          //This is actually the base.base class implementation
          MyDerived.method1();  
     }         
}

为什么不简单地将子类强制转换为特定的父类,然后调用特定的实现呢?这是一种特殊情况,应使用特殊情况解决方案。不过,您必须在children方法中使用
new
关键字

class SpecialDerived : Derived
{
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        var ptr = typeof(Base).GetMethod("Say").MethodHandle.GetFunctionPointer();            
        var baseSay = (Action)Activator.CreateInstance(typeof(Action), this, ptr);
        baseSay();            
    }
}

从前面的文章中可以看出,如果需要规避类功能,那么类架构中就有问题。这可能是真的,但在一个大型成熟项目中,不能总是重构或重构类结构。不同级别的变更管理可能是一个问题,但在重构后保持现有功能运行不变并不总是一项简单的任务,特别是在时间限制适用的情况下。在一个成熟的项目中,在代码重构之后,防止各种回归测试通过是一项相当艰巨的任务;经常会出现一些晦涩难懂的“怪事”。 在某些情况下,我们遇到了类似的问题,继承的功能不应该执行(或者应该执行其他操作)。下面我们采用的方法是将需要排除的基本代码放在一个单独的虚拟函数中。然后可以在派生类中重写该函数,并排除或更改该功能。在本例中,可以防止“文本2”在派生类中输出

public class A
{
    public int i = 0;
    internal virtual void test()
    {
        Console.WriteLine("A test");
    }
}

public class B : A
{
    public new int i = 1;
    public new void test()
    {
        Console.WriteLine("B test");
    }
}

public class C : B
{
    public new int i = 2;
    public new void test()
    {
        Console.WriteLine("C test - ");
        (this as A).test(); 
    }
}

我的2c是为了实现您需要在toolkit类中调用的功能,并在您需要的任何地方调用该功能:

public class Base
{
    public virtual void Foo()
    {
        Console.WriteLine("Hello from Base");
    }
}

public class Derived : Base
{
    public override void Foo()
    {
        base.Foo();
        Console.WriteLine("Text 1");
        WriteText2Func();
        Console.WriteLine("Text 3");
    }

    protected virtual void WriteText2Func()
    {  
        Console.WriteLine("Text 2");  
    }
}

public class Special : Derived
{
    public override void WriteText2Func()
    {
        //WriteText2Func will write nothing when 
        //method Foo is called from class Special.
        //Also it can be modified to do something else.
    }
}

这确实需要考虑访问权限,您可能需要添加一些
内部
访问器方法来促进功能。

如果您想访问基类数据,您必须使用“This”关键字或使用此关键字作为类的引用

// Util.cs
static class Util 
{
    static void DoSomething( FooBase foo ) {}
}

// FooBase.cs
class FooBase
{
    virtual void Do() { Util.DoSomething( this ); }
}


// FooDerived.cs
class FooDerived : FooBase
{
    override void Do() { ... }
}

// FooDerived2.cs
class FooDerived2 : FooDerived
{
    override void Do() { Util.DoSomething( this ); }
}
名称空间关键字
{
班级计划
{
静态void Main(字符串[]参数)
{
I=新I();
int res=i.m1();
控制台写入线(res);
控制台
public class A
{
    public int i = 0;
    internal virtual void test()
    {
        Console.WriteLine("A test");
    }
}

public class B : A
{
    public new int i = 1;
    public new void test()
    {
        Console.WriteLine("B test");
    }
}

public class C : B
{
    public new int i = 2;
    public new void test()
    {
        Console.WriteLine("C test - ");
        (this as A).test(); 
    }
}
public class Base
{
    public virtual void Foo()
    {
        Console.WriteLine("Hello from Base");
    }
}

public class Derived : Base
{
    public override void Foo()
    {
        base.Foo();
        Console.WriteLine("Text 1");
        WriteText2Func();
        Console.WriteLine("Text 3");
    }

    protected virtual void WriteText2Func()
    {  
        Console.WriteLine("Text 2");  
    }
}

public class Special : Derived
{
    public override void WriteText2Func()
    {
        //WriteText2Func will write nothing when 
        //method Foo is called from class Special.
        //Also it can be modified to do something else.
    }
}
// Util.cs
static class Util 
{
    static void DoSomething( FooBase foo ) {}
}

// FooBase.cs
class FooBase
{
    virtual void Do() { Util.DoSomething( this ); }
}


// FooDerived.cs
class FooDerived : FooBase
{
    override void Do() { ... }
}

// FooDerived2.cs
class FooDerived2 : FooDerived
{
    override void Do() { Util.DoSomething( this ); }
}
namespace thiskeyword
{
    class Program
    {
        static void Main(string[] args)
        {
            I i = new I();
            int res = i.m1();
            Console.WriteLine(res);
            Console.ReadLine();
        }
    }

    public class E
    {
        new public int x = 3;
    }

    public class F:E
    {
        new public int x = 5;
    }

    public class G:F
    {
        new public int x = 50;
    }

    public class H:G
    {
        new public int x = 20;
    }

    public class I:H
    {
        new public int x = 30;

        public int m1()
        {
           // (this as <classname >) will use for accessing data to base class

            int z = (this as I).x + base.x + (this as G).x + (this as F).x + (this as E).x; // base.x refer to H
            return z;
        }
    }
}
class A
{
    private string mystring = "A";    
    public string Method1()
    {
        return mystring;
    }
}

class B : A
{
    // this inherits Method1() naturally
}

class C : B
{
    // this inherits Method1() naturally
}


string newstring = "";
A a = new A();
B b = new B();
C c = new C();
newstring = a.Method1();// returns "A"
newstring = b.Method1();// returns "A"
newstring = c.Method1();// returns "A"