Given the following C# class definitions and code:
public class BaseClass
{
    public virtual void MyMethod()
    {
        ...do something...
    }
}
public class A : BaseClass
{
    public override void MyMethod()
    {
        ...do something different...
    }
}
public class B : BaseClass
{
    public override void MyMethod()
    {
        ...do something different...
    }
}
public class AnotherObject
{
    public AnotherObject(BaseClass someObject)
    {
        someObject.MyMethod(); //This calls the BaseClass method, unfortunately.
    }
}
I would like to call the MyMethod() that is actually found in A or B, assuming the object passed in is actually an instance of A or B, not that which is found in BaseCla开发者_Python百科ss.  Short of doing something like this:
public class AnotherObject
{
    public AnotherObject(BaseClass someObject)
    {
        A temp1 = someObject as A;
        if (A != null)
        {
            A.MyMethod();
        }
        
        B temp2 = someObject as B;
        if (B != null)
        {
            B.MyMethod();
        }
    }
}
How can I do it?
Which method is called is determined via polymorphism on the type that is passed into the AnotherObject constructor:
AnotherObject a = new AnotherObject(new A()); // invokes A.MyMethod() 
AnotherObject b = new AnotherObject(new B()); // invokes B.MyMethod() 
AnotherObject c = new AnotherObject(new BaseClass()); //invokes BaseClass.MyMethod() 
Sorry, but you are completely mistaken; this would go against the entire point of virtual methods. If someObject is an A then A.MyMethod will be invoked. If someObject is a B then B.MyMethod will be invoked. If someObject is a BaseClass and not an instance of a type derived from BaseClass then BaseClass.MyMethod will be invoked.
Let's use everyone's favorite example:
class Animal {
    public virtual void Speak() {
        Console.WriteLine("i can haz cheezburger?");
    } 
}
class Feeder {
    public void Feed(Animal animal) { animal.Speak(); }
}
class Cat : Animal {
    public override void Speak() { Console.WriteLine("Meow!"); }
}
class Dog : Animal {
    public override void Speak() { Console.WriteLine("Woof!"); }
}
Then:
Animal a = new Animal();
Animal c = new Cat();
Animal d = new Dog();
Feeder f = new Feeder();
f.Feed(a);
f.Feed(c);
f.Feed(d);
This will print:
i can haz cheezburger?
Meow!
Woof!
Again, this is the entire point of virtual methods.
Further, we can go to the specification. From 10.6.3 (Virtual methods)
In a virtual method invocation, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke.
(Bolding and italics in original.)
In precise terms, when a method named
Nis invoked with an argument listAon an instance with a compile-time typeCand a run-time typeR(whereRis eitherCor a class derived fromC), the invocation is processed as follows:• First, overload resolution is applied to
C,N, andA, to select a specific methodMfrom the set of methods declared in and inherited byC. This is described in §7.5.5.1.• Then, if
Mis a non-virtual method,Mis invoked.• Otherwise,
Mis a virtual method, and the most derived implementation ofMwith respect to R is invoked.
(Bolding not in original.)
Then, we need the definition of "most derived implementation of M." This is a nice recursive definition:
The most derived implementation of a virtual method
Mwith respect to a classRis determined as follows:• If
Rcontains the introducing virtual declaration ofM, then this is the most derived implementation ofM.• Otherwise, if
Rcontains an override ofM, then this is the most derived implementation ofM.• Otherwise, the most derived implementation of
Mwith respect toRis the same as the most derived implementation ofMwith respect to the direct base class ofR.
Thus, in our example above with Cat : Animal and Dog : Animal, when the parameter a to Feeder.Feed(Animal) is an instance of Cat then Cat.Speak is the most derived implementation. This is why we will see "Meow!" and not "i can haz cheezburger?"
If MyMethod() is abstract on the base class, then the version in the derived classes will be used. So if you don't need to call the instance in the base class, this would be an option.
    static void Main(string[] args)
    {
        A classA = new A();
        B classB = new B();
        DoFunctionInClass(classA);
        DoFunctionInClass(classB);
        DoFunctionInClass(classA as BaseClass);
        Console.ReadKey();
    }
    public static void DoFunctionInClass(BaseClass c) 
    {
        c.MyMethod();
    }
public abstract class BaseClass
{
    public abstract void MyMethod();
}
public class A : BaseClass
{
    public override void MyMethod()
    {
        Console.WriteLine("Class A");
    }
}
public class B : BaseClass
{
    public override void MyMethod()
    {
        Console.WriteLine("Class B");
    }
}
If someObject passed in is class A, then A.MyMethod is called, not the base class implementation. Also look at the is keyword.
Because you've typed it as a BaseClass instead of an A or a B, the baseclass is the begin point for the method calls.
You might try using a generic:
public class AnotherObject 
{ 
    public AnotherObject<T>(T someObject) where T : BaseClass
    { 
        someObject.MyMethod(); //This calls the BaseClass method, unfortunately. 
    } 
} 
I'm not sure how well this will fly in the constructor, but you might be able to move this to a different method.
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论