Home > Software engineering >  Cast from base generic type to derived generic type where the derived type has additional type const
Cast from base generic type to derived generic type where the derived type has additional type const

Time:01-25

Actually whilst casting would be the ideal even "newing up" the derived type would work in my specific scenario. I suspect this isn't possible when I don't have access to the concrete type of the generic parameter.

public class OrderableCollection<T> : Collection<T> where T : IOrderable, new()
{
...
}

public class ArchivableOrderableCollection<T> : OrderableCollection<T> where T : IOrderable, IArchivable, new()
{
...
}

public class OrderableListDisplay<TItem> where TItem : IOrderable, new()
{
    protected OrderableCollection<TItem> orderableItems { get; set; }

    protected virtual async Task RestoreItem(TItem item)
    {
        if (item is not IArchivable)
        {
            throw new ArgumentException();
        }

        // None of these compile
        var aoc1 = orderableItems as ArchivableOrderableCollection<TItem>;
        var aoc2 = new ArchivableOrderableCollection<TItem>(orderableItems);
        var aoc3 = (ArchivableOrderableCollection<TItem>)(object)(OrderableItems);

        // I think I need something like
        var aoc4 = orderableItems as ArchivableOrderableCollection<TItem> where TItem : IArchivable
    }  
}

CodePudding user response:

This worked for me

    where T : TItem, IArchivable
{
    if( orderableItems is not ArchivableOrderableCollection<T> items )
    {
        throw new InvalidOperationException();
    }

   
    items.Restore( item );
}

CodePudding user response:

You could add a generic argument w/ constraints to your RestoreItem method

protected virtual async Task RestoreItem<T>(T item)
    where T : TItem, IArchivable
{
    if( orderableItems is not ArchivableOrderableCollection<T> items )
    {
        throw new InvalidOperationException();
    }

    // do what you need to here
    items.Restore( item );
}

However, I think you should reconsider your design. Implement base and derived classes for OrderableListDisplay<T> so that a derived version may constrain the TItem to IArchivable properly and expects and implementation of ArchivableOrderableCollection<T>:

public class OrderableListDisplay<TItem>
    where TItem : IOrderable, new()
{
    private readonly OrderableCollection<TItem> _items = null;

    public OrderableListDisplay( OrderableCollection<TItem> items )
    {
        _items = items ?? throw new ArgumentNullException( nameof( items ) );
    }
}

public class ArchivableOrderableListDisplay<TItem>
    : OrderableListDisplay<TItem>
    where TItem : IArchivable
{
    private readonly ArchivableOrderableCollection<TItem> _items = null;

    public ArchivableOrderableListDisplay( ArchivableOrderableCollection<TItem> items )
        : base( items )
    {
        _items = items;
    }

    protected async Task RestoreItem( TItem item )
    {
        _items.Restore( item );
    }
}
  •  Tags:  
  • Related