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 NewThing
s (as opposed to OriginalThings
, but you can pass them around as OriginalThing
s 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.
精彩评论