2009-08-26 2 views
48

Учитывая следующий код, есть ли способ, которым я могу назвать версию класса X метода X?Как я могу назвать «базовую реализацию» переопределенного виртуального метода?

class A 
{ 
    virtual void X() { Console.WriteLine("x"); } 
} 

class B : A 
{ 
    override void X() { Console.WriteLine("y"); } 
} 

class Program 
{ 
    static void Main() 
    { 
    A b = new B(); 
    // Call A.X somehow, not B.X... 
    } 

ответ

78

Использование конструкций # языка C, вы не можете явно вызвать базовую функцию из вне объем A или B. Если вам действительно нужно это сделать, тогда есть недостаток в вашем дизайне - то есть, эта функция не должна быть виртуальной для начала, или часть базовой функции должна быть выделена отдельной не виртуальной функции.

Вы можете из внутри B.X однако называют A.x

class B : A 
{ 
    override void X() { 
    base.X(); 
    Console.WriteLine("y"); 
    } 
} 

Но что-то другое.

Как Саша Труф указывает на this answer, вы можете сделать это через ИЛ. Возможно, вы также можете выполнить это через отражение, как указывает mhand в комментариях.

+6

(Привет Просто для записи, кто-то удалил тег в «тупых-трик, что я добавил, а потом кто-то else удалил комментарий, указав его, заставив его выглядеть так, как будто я действительно хочу/должен это сделать. Было бы полезно получить уведомление о глупых изменениях, которые люди, похоже, хотят сделать на SO.) – mackenir

+0

Вызов AX() изнутри B это единственная ситуация, когда я даже вижу, что вам нужно называть ее когда-то чрезмерно. Скажем, у вас был метод копирования с членами базового класса, затем переопределить его, чтобы добавить функции копирования для новых членов и вызвать base.copy() внутри, чтобы все копировались. – steviesama

+0

Интересно, я бы подумал, что это может быть достигнуто путем отражения? – mhand

6

Вы не можете, и вы не должны. Для этого нужен полиморфизм, так что каждый объект имеет свой собственный способ делать некоторые «базовые» вещи.

7

Вы можете сделать это, но не в том месте, которое вы указали. В контексте B вы можете вызывать A.X() по телефону base.X().

4

I konow это история вопрос сейчас. Но для других гуглеров: вы могли бы написать что-то вроде этого. Но это требует изменения базового класса, что делает его бесполезным для внешних библиотек.

class A 
{ 
    void protoX() { Console.WriteLine("x"); } 
    virtual void X() { protoX(); } 
} 

class B : A 
{ 
    override void X() { Console.WriteLine("y"); } 
} 

class Program 
{ 
    static void Main() 
    { 
    A b = new B(); 
    // Call A.X somehow, not B.X... 
    b.protoX(); 


    } 
10

Вы не можете сделать это C#, но вы можете редактировать MSIL.

IL код вашего Main метод:

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    .maxstack 1 
    .locals init (
     [0] class MsilEditing.A a) 
    L_0000: nop 
    L_0001: newobj instance void MsilEditing.B::.ctor() 
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: callvirt instance void MsilEditing.A::X() 
    L_000d: nop 
    L_000e: ret 
} 

Вы должны изменить опкод в L_0008 от callvirt к вызову

L_0008: call instance void MsilEditing.A::X() 
2

Это невозможно, если метод объявлен в производный класс как overrides. чтобы сделать это, метод в производном классе должен быть объявлен как new:.

public class Base { 

    public virtual string X() { 
     return "Base"; 
    } 
} 
public class Derived1 : Base 
{ 
    public new string X() 
    { 
     return "Derived 1"; 
    } 
} 

public class Derived2 : Base 
{ 
    public override string X() { 
     return "Derived 2"; 
    } 
} 

Derived1 a = new Derived1(); 
Base b = new Derived1(); 
Base c = new Derived2(); 
a.X(); // returns Derived 1 
b.X(); // returns Base 
c.X(); // returns Derived 2 

See fiddle here

Смежные вопросы