【问题标题】:Cast object to class that implements it [closed]将对象转换为实现它的类[关闭]
【发布时间】:2018-09-11 20:10:34
【问题描述】:

系统类

public class View
{
    //5 different constructors

    public virtual bool OnTouchEvent(MotionEvent e)
    {
        //Can't see inside
    }
}

我需要覆盖这个OnTouchEvent,所以我尝试这样:

public class MyClass : SystemClass
{
    public override View GetCellCore(/*params*/)
    {
        View v = base.GetCellCore(/*params*/);
        MyView mv = (MyView)mv;
        return mv;
    }

    private class MyView : View
    {
        //Implementation of the 5 different constructors

        public override bool OnTouchEvent(MotionEvent e)
        {
            //Do something
            return base.OnTouchEvent(e);
        }
    }
}

我需要覆盖此OnTouchEvent,以便获取触摸信息。

【问题讨论】:

    标签: c# class casting


    【解决方案1】:

    你试图做的事情因为这行不通的原因而行不通:

    object obj = new object();
    Dog dog = (Dog)object;
    

    Dog 继承自 object 就像它继承自 Animal 一样(因为一切都继承自 object。)但是您可能会明白为什么能够这样做没有意义。举个例子:

    Animal cat = new Cat();
    Dog dog = (Dog)cat;
    
    object date = DateTime.Now;
    Dog dog = (Dog)date; 
    

    如果对象可以这样转换,那么实际上任何东西都可以转换为其他任何东西,类型就没有意义了。

    另一种看待它的方式是一个对象只有一种类型。如果创建Dog 的实例,则该对象的类型为Dog。它永远不会是其他任何东西,永远。它可以被转换为其基本类型之一或被转换为它实现的接口,但这不会改变它的类型。

    举例说明:

    Dog dog = new Dog(); // It's a Dog
    Animal animal = (Animal)dog; // It's cast as an Animal, but it's still a Dog.
    object obj = (object)animal; // It's cast as an object, but it's still a Dog.
    

    也许这有助于证明强制转换不能也不会改变对象的类型。因此,将Animal 转换为Dog 的唯一方法是Animal 已经Dog

    像这样:

    var poodle = new Poodle(); // inherits from Dog
    var animal = (Animal)poodle;
    var dog = (Dog)animal;
    

    这不会引发异常,因为贵宾犬是AnimalDog. 如果这消除了任何混淆,在这三行代码执行之后,仍然只有一个对象。我们没有创建新对象,只是引用同一个对象的新变量。

    【讨论】:

    • 解释得很好
    【解决方案2】:

    狗是动物(继承) Animal 并不总是 Dog(这就是它在您的示例中没有运行的原因)但可能是 Dog(这就是它编译的原因)。

    【讨论】:

      【解决方案3】:

      我认为尽可能接近的是 Dog 上的 Animal 构造函数。但这仍然没有多大意义。

      public class Dog : Animal 
      {
          public void Woof()
          { }
          public int DogTag { get; set; }  //you would have to make this up
          public Dog()
          { }
          public Dog (Animal animal) 
          {
              //now the dog is nothing more than an animal
          }
      }
      
      Dog dog = new Dog(animal);
      

      【讨论】:

      • 但是,如果提供的AnimalCat,你有一个问题。
      • @HimBromBeere 不,你没有。狗不过是动物。
      【解决方案4】:

      Animal是一个系统类,对象是内部创建的

      这是不可能的,因为根本无法保证您的系统类确实是您的自定义类之一。但是,如果您不能影响系统类,则可以实现自定义转换逻辑。

      public sealed class SystemClass
      {
      }
      
      public class CustomClass
      {
          private SystemClass _systemClass;
      
          public CustomClass(SystemClass systemClass)
          {
              _systemClass = systemClass;
          }
      
          public static explicit operator CustomClass(SystemClass systemClass)
          {
              return new CustomClass(systemClass);
          }
      
          public static implicit operator SystemClass(CustomClass customClass)
          {
              return customClass._systemClass;
          }
      }
      

      这样您就可以添加附加功能,同时保持与底层基础架构的兼容性。

      var system = new SystemClass();
      var custom = (CustomClass)system;
      

      【讨论】:

      • 进行显式转换是一个非常糟糕的想法,因为并非每个Animal都可以转换为Dog
      • 我真的不建议这样做。首先,它要求您“弥补”Dog 的一些属性,以便创建一个新属性。
      • 这无论如何都不会编译,因为转换运算符不能转换到派生类/从派生类转换(错误 CS0554)。
      猜你喜欢
      • 2011-07-21
      • 2010-12-08
      • 2013-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      • 2012-12-22
      相关资源
      最近更新 更多