Home > Net >  How to avoid downcast in derived class
How to avoid downcast in derived class

Time:12-26

I have parent class (Base) and child class (Derived). Then another interface use Base as the Generic Type and within that interface call IsDataEqual on derived objects.

That interface receives many implementations of this derived object since it use generic with type constraint to Base.

 public interface IMyLogic<T> where T : Base

Everything works fine but I feel bad about having this downcast. Is there anyway to avoid it ?

public abstract class Base
{
    public abstract bool IsDataEqual(Base data);
}

public class Derived : Base
{
    public string x;
    public string Y;

    public override bool IsDataEqual(Base data)
    {
        if(data.GetType() != typeof(Derived))
        {
            //Type mismatch
            throw new Exception();
        }

        Derived derriveData = data as Derived; //downcast
        
        if (this.x == derriveData.x || this.y == derriveData.y)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

p.s. I can not move x and y to base class due to business logic.

CodePudding user response:

For me, I will use IEquatable<T> to replace your IsDataEqual. I'm not sure could you change your base class or not but these is for your reference

public abstract class Base : IEquatable<Base>
{
    public bool Equals(Base? other)
    {
        throw new NotImplementedException();
    }
}

public class Derived : Base, IEquatable<Derived>
{
    public string x;
    public string Y;

    public bool Equals(Derived? obj)
    {
        throw new NotImplementedException();
    }
}

CodePudding user response:

This kind of comparison suggest value type semantics, so I would suggest using records to get value-based comparison out-of-the-box (requires c#9 or higher).

Unfortunately, though, we don't have a generic constraint for records for you to use in your interface (that would look like public interface IMyLogic<T> where T : record), but since records can only inherit from other records (see here), it's enough to simply change your base type to a record (you won't need the IsDataEqual() abstract method anymore, but I'm assuming that's not the only reason for you to have a base class)

  • Related