【问题标题】:C# casting and inheritanceC# 强制转换和继承
【发布时间】:2011-08-31 17:18:12
【问题描述】:

我有一个经常传递的对象。

我需要添加一条数据,不能修改基类

所以我有

static OriginalThing GetNewThing()
{
  return new OriginalThing();
}

现在我想添加我的数据

class EnhancedThing : OriginalThing
{
  string name;
  static EnhancedThing GetNewThing(string name)
  {
     EnhancedThing ething = new OriginalThing();   <---doesnt work even if i cast it
     ething.Name = name;
  }
}

我该怎么做?

【问题讨论】:

    标签: c# inheritance casting


    【解决方案1】:

    您不能将OriginalThing 分配给NewThing,因为它不是NewThing。反之亦然,因为NewThing 可以胜任OriginalThing 的所有功能,但反之则不然。

    只需创建EnhancedThing 的实例,分配名称,然后返回即可。您可以将EnhancedThing 视为OriginalThing,因为它OriginalThing

    class EnhancedThing : OriginalThing
    {
      public string Name { get; private set; }
      static EnhancedThing GetNewThing(string name)
      {
         EnhanedThing thing = new EnhancedThing();
         thing.Name = name;
         return thing;
      }
    }
    
    // ...
    
    OriginalThing foo = EnhancedThing.GetNewThing( "someName" );
    

    还要意识到,name 当前是一个私有成员变量(在您的示例中),您将无法访问 NewThing 对象的任何其他功能,除非您将它们视为NewThings(相对于OriginalThings,但如果需要,您可以将它们传递为OriginalThings)

    【讨论】:

    • 很好的解释 Ed。我只想补充一点,您可能会听到这被讨论为协方差与逆变(尤其是在采访中;-)blogs.msdn.com/b/csharpfaq/archive/2010/02/16/…
    • EnhancedThing ething = new OriginalThing();当我这样做时,它表明您不能隐式转换类型
    • @Jeff:这是复制原始代码留下的错字,抱歉。
    【解决方案2】:

    你需要这样做:

    EnhancedThing ething = new EnhancedThing();
    

    【讨论】:

      【解决方案3】:

      这是因为 OriginalThing 不是 EnhancedThing,但 EnhancedThing 是 OriginalThing。

      您可以做的一件事是为 EnhancedThing 创建一个构造函数,该构造函数接受 OriginalThing 并复制适用的成员。

      class EnhancedThing : OriginalThing
      {
          public EnhancedThing()
          {
              // default constructor
          }
      
          public EnhancedThing( OriginalThing src )
          {
              // copy over the significant items
          }
      }
      

      【讨论】:

        【解决方案4】:

        如果其他类是密封的,您可以在新类中使用封装,然后修改/扩展 API。然后,您可以定义从一个对象到另一个对象的隐式转换,并不进行转换交替使用这些类型。

        这是否适合您的情况取决于您打算做什么以及您想要实现的目标,但这是一项有价值的技术。它对于隐藏原始的部分/所有成员和重新定义 API 更有用。

        // no need to cast
        EnhancedThing thing = new OriginalThing();
        var result = thing.NewMethod();
        
        // again no need to cast, treat as original when passing around
        OriginalThing original = thing;
        
        public class EnhancedThing
        {
            private readonly OriginalThing originalThing;
        
            public static implicit operator OriginalThing(EnhancedThing enhancedThing)
            {
                return enhancedThing.originalThing;
            }
        
            public static implicit operator EnhancedThing(OriginalThing originalThing)
            {
                return new EnhancedThing(originalThing);
            }
        
            private EnhancedThing(OriginalThing originalThing)
            {
                this.originalThing = originalThing;
            }
        
            public string OriginalMethod()
            {
                return originalThing.OriginalMethod();
            }
        
            public string NewMethod()
            {
                var value = originalThing.OriginalMethod();
                // extra processing ...
                return value;
            }
        }
        

        此技术在 Sitecore 中广泛使用,以提供来自通用基础实现的不同数据类型模型。需要注意的是,如果您打算添加一个新的数据字段,它将在 upcast 时丢失。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-21
          • 1970-01-01
          • 2011-11-17
          • 2011-01-05
          • 2010-11-30
          • 2012-02-04
          相关资源
          最近更新 更多