开发者

C# casting and inheritance

I have an object that I pass around a lot.

I need to add a piece of data to it and cannot modify the base class

So I have

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

Now i want to add my piece of data

class EnhancedThing : OriginalThing
{
  string name;
  static EnhancedThing GetNewThing(string name)
  {
     EnhancedThing ething = new Orig开发者_运维知识库inalThing();   <---doesnt work even if i cast it
     ething.Name = name;
  }
}

How do I do this?


You can't assign an OriginalThing to a NewThing because it simply is not a NewThing. The other way around works fine because a NewThing is capable of everything an OriginalThing is, but the reverse is not true.

Just create an instance of EnhancedThing, assign the name, and return it. You can treat the EnhancedThing as if it were an OriginalThing because it is an 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" );

Also realize that doesn't buy you much as name is currently a private member variable (in your example), and you won't be able to access any additional functionality of NewThing objects unless you treat them as NewThings (as opposed to OriginalThings, but you can pass them around as OriginalThings if needed)


You need to do this:

EnhancedThing ething = new EnhancedThing();


This is because an OriginalThing is not an EnhancedThing, but an EnhancedThing is an OriginalThing.

One thing you could do is have a constructor for EnhancedThing that takes an OriginalThing and copies over the members that apply.

class EnhancedThing : OriginalThing
{
    public EnhancedThing()
    {
        // default constructor
    }

    public EnhancedThing( OriginalThing src )
    {
        // copy over the significant items
    }
}


If the other class is sealed you can use encapsulation in your new class, and then modify/extend the API. You can then define a implicit cast from one object to the other and use these types interchangeably without casting.

Whether this is suitable in your case comes down to what you intend to do, and what you are trying to achieve but it's a valuable technique. It's more useful for hiding some/all members of the original and redefining an 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;
    }
}

This technique is used extensively in Sitecore to provide different data type Models from a common base implementation. One caveat if you intend to add a new data field, it will be lost on upcast.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜