【问题标题】:Downcasting safety向下铸造安全
【发布时间】:2014-01-04 21:01:03
【问题描述】:

代码如下:

Base b = new Derived(); // Upcasting
// Some actions
Derived d = (Derived)b; // Downcasting 

据我了解,引用就像您正在查看某块内存的模板。向上转型只是缩小了模板,因此您无法访问使用 Derived 类添加的成员。而这里的向下投射又将模板扩展回来。

问题是: 由于没有保留对类型派生部分的引用,因此只保留了 Base。 GC 的某些操作或活动是否会在向下转换发生时擦除或覆盖曾经包含 Derived 成员的内存块?换句话说,向下转换Derived d = (Derived)b 会失败吗?

【问题讨论】:

  • 可以,但前提是b 不是Derived
  • 谢谢,我知道了。但是类型的 Derived 部分是否会丢失,因为没有对它的引用只保留了 Base 部分。

标签: c# downcast


【解决方案1】:

变量指向实际对象所在的内存位置。如果您创建了Derived 类型的对象,则该变量指向该类型的实例所在的内存位置。即使您使用基本类型Base,内存中的实例也是您实例化的类型。因此,只要您确定 b 的类型为 Derived,就不会失败。

【讨论】:

    【解决方案2】:

    在上下文中这是一个安全的演员表。您已创建 Derived 实例 这就是为什么将 Derived 视为 Derived 总是安全的;没有GC 活动可能会破坏实例的一部分。铸造是一种 治疗(我将实际 Derived istance 视为 仅限Base:我承诺只调用一部分方法、属性) 并且投射到自身总是安全的

      // Actual instance is derived, but I'm going to restrict 
      // my work with them: I've promissed not to call for "b"
      // any derived methods/properties  
      Base b = new Derived(); 
    
      // What is the actual type of "b"?
      String typeName = b.GetType().Name; // <- "Derived"
    
      // Try to convert to Derived 
      // This's better way to cast then (Derived) b
      Derived d = b as Derived;
    
      // Since "b" is actually Derived d will ne not null
      if (Object.RefrenceEquals(null, d)) {
        Console.Write("b is Derived");
      }
    
      // You can also check
      if (b is Derived) {
        Console.Write("b is a Derived instance.");
      }
    

    【讨论】:

    • 这就是我一直在寻找的答案。非常感谢!
    【解决方案3】:

    不,它不会丢失信息。但是,如果这些信息一开始就没有,那么演员表可能会失败。如果 b 从来不是 Derived 类型或派生类型,则会抛出异常。

    Base b = new b();
    // Some actions
    Derived d = (Derived)b; // will fail, b never was of type Derived.
    

    【讨论】:

      【解决方案4】:

      1) 到存储 b 的“GC 将擦除 ... 内存块”时,您的代码“= (Derived)b” b 不再在内存中,当然它会失败,但 GC 应该不要删除它,除非你在玩弱引用。

      2) 基 b = new Derived(); 我不明白你为什么要这样做“向上转型”。 您的代码已经具有 Derived 的强引用/类型,不妨使用 Derived b = ....

      【讨论】:

      • 1) 不是整个 b - 只是 Derived 添加到 base 的成员,只要我们有仅引用 Base 部分的变量。 2)这个问题不是实际的,而是理论上的。 :)
      • 当您将 b 创建为 Derived 时,所有成员/道具都存储在 mem 中。 Base 类型的工作方式就像一个掩码/铸造,但在它下面实际上是 Derived。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      • 2021-11-09
      • 1970-01-01
      • 2019-07-21
      • 2010-12-27
      • 1970-01-01
      相关资源
      最近更新 更多