从基本泛型类型转换为派生泛型类型,其中派生类型具有额外的类型约束
Cast from base generic type to derived generic type where the derived type has additional type constraints
实际上,虽然转换是理想的,但即使“更新”派生类型也适用于我的特定场景。我怀疑当我无法访问泛型参数的具体类型时这是不可能的。
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
}
}
您可以向 RestoreItem
方法添加一个带约束的通用参数
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 );
}
但是,我认为您应该重新考虑您的设计。为 OrderableListDisplay<T>
实现基础和派生 类,以便派生版本可以正确地将 TItem
约束为 IArchivable
,并期望和实现 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 );
}
}
这对我有用
protected virtual async Task RestoreItem<T>(T item)
where T : TItem, IArchivable
{
if( orderableItems is not ArchivableOrderableCollection<T> items )
{
throw new InvalidOperationException();
}
items.Restore( item );
}
实际上,虽然转换是理想的,但即使“更新”派生类型也适用于我的特定场景。我怀疑当我无法访问泛型参数的具体类型时这是不可能的。
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
}
}
您可以向 RestoreItem
方法添加一个带约束的通用参数
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 );
}
但是,我认为您应该重新考虑您的设计。为 OrderableListDisplay<T>
实现基础和派生 类,以便派生版本可以正确地将 TItem
约束为 IArchivable
,并期望和实现 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 );
}
}
这对我有用
protected virtual async Task RestoreItem<T>(T item)
where T : TItem, IArchivable
{
if( orderableItems is not ArchivableOrderableCollection<T> items )
{
throw new InvalidOperationException();
}
items.Restore( item );
}