【问题标题】:C# General inexplicit upcast of instance by typeC# 按类型对实例进行一般不明确的向上转换
【发布时间】:2017-07-05 16:31:13
【问题描述】:

你能给我解释一下吗? 我必须如何解决下面的简单任务?

class Base{}
class Derived1: Base { void Method(); }
class Derived2: Base { void Method();}

static void Main(string[] args)
{   
    Base object; //it is just a declaring

    if (some condition is true)
        object = new Derived1();
    else
        object = new Derived2();

    //now i want to call one of methods of one of my derived classes
    //object.MyMethod(); //of course wrong, object has no that method

    //ok, i have to downcast it but i don't know which class to
    //((object.GetType())object).Method(); //wrong

    //is there only one way is to repeat conditions 
    //and to downcast explicitly?

    if (some condition is true again)
        (object as Derived1).Method();
    else
        (object as Derived2).Method();
}

当然,基类对 Method() 一无所知。

【问题讨论】:

  • 如果有理由从基类派生,即 Derived1 和 Derived2 相关,则在基类上抽象或虚拟化您的方法;那么你就不需要投了。目前,您好像想说if(x) then buy milk else tell the dog to bark

标签: c# typeof downcast gettype


【解决方案1】:

我建议在 Base 类中使用 abstract 方法 overriden 在两个派生类中:

abstract class Base { public abstract void Method();}
class Derived1: Base { public override void Method(); }
class Derived2: Base { public override void Method(); }

然后

static void Main(string[] args) {   
  Base instance; 

  if (some condition is true)
    instance = new Derived1();
  else
    instance = new Derived2();

  instance.Method();
}

实现 interface 是另一种选择:

interface IBase {void Method();}

class Derived1: IBase { void Method(); }
class Derived2: IBase { void Method(); }

static void Main(string[] args) {   
  IBase instance; 

  if (some condition is true)
    instance = new Derived1();
  else
    instance = new Derived2();

  instance.Method();
}

【讨论】:

    【解决方案2】:

    如果该类仅用于声明并且没有任何具体方法,请使用interface

    interface Base{
    void Method();
    }
    
    class Derived1: Base { void Method(){} }
    class Derived2: Base { void Method(){}}
    
        static void Main(string[] args)
    {   
        Base obj; //it is just a declaring
    
        if (some condition is true)
            obj = new Derived1();
        else
            obj = new Derived2();
    
     //Call it directly
            obj.Method();    
    }
    

    【讨论】:

      【解决方案3】:

      您需要了解的是继承多态性的用途。

      继承

      允许相关对象从一个共同的祖先派生。

      abstract class Shape
      {
      }
      
      sealed class Rectangle : Shape
      {
      }
      
      sealed class Circle : Shape
      {
      }
      

      多态性

      允许派生类型具有不同的实现来执行共同的行为。

      abstract class Shape
      {
          abstract double GetArea();
      }
      
      sealed class Rectangle : Shape
      {
          override double GetArea() // same behaviour
          {
              return x * y; // different implementation
          }
      }
      
      sealed class Circle : Shape
      {
          override double GetArea() // same behavior
          {
              return PI * r * r; // different implementation
          }
      }
      

      接口与抽象类

      接口定义对象可以做什么。在下面的示例中,DogCat 实现了 IAudible 接口,该接口公开了一个 MakeNoise 方法。注意,IAudible 不是对象,它可以做的事情

      class Dog : IAudible
      {
          public void MakeNoise()
          {
              Console.WriteLine("Woof");
          }
      }
      
      class Cat : IAudible
      {
          public void MakeNoise()
          {
              Console.WriteLine("Meow")
          }
      }
      
      IAudible d = new Dog();
      d.MakeNoise(); // Woof
      
      IAudible c = new Cat();
      c.MakeNoise(); // Meow
      

      抽象类定义对象是什么。在下面的示例中,DogCat 扩展了 Animal,因为狗和猫都是动物

      abstract class Animal
      {
          public string Noise { get; protected set; }
      }
      
      sealed class Dog : Animal
      {
          public Dog()
          {
              Noise = "Woof";
          }
      }
      
      sealed class Cat : Animal
      {
          public Cat()
          {
              Noise = "Meow";
          }
      }
      
      Animal d = new Dog();
      d.Noise; // Woof;
      
      Animal c = new Cat();
      c.Noise; // Meow
      

      要回答您的问题,请确定您的对象之间的关联方式和原因。如果他们与他们能做什么相关,那么使用一个接口。如果它们之间存在关联,请使用抽象类。

      【讨论】:

      • 很清楚。谢谢
      【解决方案4】:

      同意每个答案。谢谢大家。

      但还有一个 ..crutch.. 使用委托

      class Base
      {
          public delegate string Method();
          public Method m;
      }
      class Derived1 : Base
      {
          public string ParticularMethod()
          {
              return "Particular method of derived 1";
          }
      }
      class Derived2 : Base
      {
          public string ParticularMethod()
          {
              return "Particular method of derived 2";
          }
      }
      
      class Program
      {
          static void Main(string[] args)
          {
              Base obj; //it is just a declaring
      
              if (true)
              {
                  obj = new Derived1();
                  obj.m = (obj as Derived1).ParticularMethod;
              }
              else
              {
                  obj = new Derived2();
                  obj.m = (obj as Derived2).ParticularMethod;
              }
      
              Console.WriteLine(obj.m());
              //"Particular method of derived 1"
              Console.ReadKey();
      
          }
      }
      

      【讨论】:

        【解决方案5】:

        还是这样

        dynamic obj; //it is just a declaring
        
        if (true)
            obj = new Derived1();
        else
            obj = new Derived2();
        
        Console.WriteLine(obj.ParticularMethod());
        //"Particular method of derived 1"
        Console.ReadKey();
        

        它也有效

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-31
          • 2015-10-10
          • 2019-09-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多