Introduction
I am aware that \"user-defined conversions to or from a base class are not allowed\". MSDN gives, as an explanation to this rule, \"You
you can use generic, its possible like blow
public class a<based>
{
public static implicit operator b(a<based> v)
{
return new b();
}
}
public class b
: a<b>
{
}
Ugg, I ended up just doing a simple Cast() method inside my modified entity. Maybe I am just missing the point, but I need to modify my base type so I can keep my code inside the new object to do x. I would have used public static explicit operator if the compiler would let me. The inheritance messes it up explicit cast operator.
Usage:
var newItem = UpgradedEnity(dbItem);
var stuff = newItem.Get();
Sample:
public class UpgradedEnity : OriginalEnity_Type
{
public string Get()
{
foreach (var item in this.RecArray)
{
//do something
}
return "return something";
}
public static UpgradedEnity Cast(OriginalEnity_Type v)
{
var rv = new UpgradedEnity();
PropertyCopier<OriginalEnity_Type, UpgradedEnity>.Copy(v, rv);
return rv;
}
public class PropertyCopier<TParent, TChild> where TParent : class
where TChild : class
{
public static void Copy(TParent from, TChild to)
{
var parentProperties = from.GetType().GetProperties();
var childProperties = to.GetType().GetProperties();
foreach (var parentProperty in parentProperties)
{
foreach (var childProperty in childProperties)
{
if (parentProperty.Name == childProperty.Name && parentProperty.PropertyType == childProperty.PropertyType)
{
childProperty.SetValue(to, parentProperty.GetValue(from));
break;
}
}
}
}
}
}
It's not a design flaw. Here's why:
Entity entity = new Body();
Body body = (Body) entity;
If you were allowed to write your own user-defined conversion here, there would be two valid conversions: an attempt to just do a normal cast (which is a reference conversion, preserving identity) and your user-defined conversion.
Which should be used? Would you really want is so that these would do different things?
// Reference conversion: preserves identity
Object entity = new Body();
Body body = (Body) entity;
// User-defined conversion: creates new instance
Entity entity = new Body();
Body body = (Body) entity;
Yuk! That way madness lies, IMO. Don't forget that the compiler decides this at compile-time, based only on the compile-time types of the expressions involved.
Personally I'd go with solution C - and possibly even make it a virtual method. That way Body
could override it to just return this
, if you want it to be identity preserving where possible but creating a new object where necessary.
The reason you can't do it is because it's not safe in the general case. Consider the possibilities. If you want to be able to do this because the base and derived class are interchangeable, then you really only have one class and you should merge the two. If you want to have your cast operator for the convenience of being able to downcast base to derived, then you have to consider that not every variable typed as the base class will point to an instance of the specific derived class you are trying to cast it to. It might be that way, but you would have to check first, or risk an invalid cast exception. That's why downcasting is generally frowned upon and this is nothing more than downcasting in drag. I suggest you rethink your design.
Well, when you are casting Entity
to Body
, you are not really casting one to another, but rather casting the IntPtr
to a new entity.
Why not create an explicit conversion operator from IntPtr
?
public class Entity {
public IntPtr Pointer;
public Entity(IntPtr pointer) {
this.Pointer = pointer;
}
}
public class Body : Entity {
Body(IntPtr pointer) : base(pointer) { }
public static explicit operator Body(IntPtr ptr) {
return new Body(ptr);
}
public static void Test() {
Entity e = new Entity(new IntPtr());
Body body = (Body)e.Pointer;
}
}
(Invoking necromancy protocols...)
Here's my use-case:
class ParseResult
{
public static ParseResult Error(string message);
public static ParseResult<T> Parsed<T>(T value);
public bool IsError { get; }
public string ErrorMessage { get; }
public IEnumerable<string> WarningMessages { get; }
public void AddWarning(string message);
}
class ParseResult<T> : ParseResult
{
public static implicit operator ParseResult<T>(ParseResult result); // Fails
public T Value { get; }
}
...
ParseResult<SomeBigLongTypeName> ParseSomeBigLongTypeName()
{
if (SomethingIsBad)
return ParseResult.Error("something is bad");
return ParseResult.Parsed(new SomeBigLongTypeName());
}
Here Parsed()
can infer T
from it's parameter, but Error
can't, but it can return a typeless ParseResult
that is convertible to ParseResult<T>
- or it would be if not for this error. The fix is to return and convert from a subtype:
class ParseResult
{
public static ErrorParseResult Error(string message);
...
}
class ErrorParseResult : ParseResult {}
class ParseResult<T>
{
public static implicit operator ParseResult<T>(ErrorParseResult result);
...
}
And everything is happy!