无法转换协变通用接口
Unable to cast covariant generic interfaces
我有两个接口:
public interface ISnack { }
public interface IWrapper<TSnack> where TSnack : ISnack
{
void Wrap(TSnack snack);
}
还有两个类:
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
CheeseCake c;
public void Wrap(CheeseCake snack)
{
c = snack;
}
}
public class CheeseCake : ISnack { }
我要执行
IWrapper<ISnack> wrappedSnack = (IWrapper<ISnack>)(new CheeseCakeContainer());
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
但这会抛出一个无效的转换异常
System.InvalidCastException: 'Unable to cast object of type
'CheeseCakeContainer' to type 'IWrapper`1[ISnack]'.'
我应该更改什么才能使转换工作?我正在使用 C#9 和 .NET5
问题的症结在于您正在尝试创建一个 协变 的容器,或者您正在将更派生的类型分配给更通用的类型(CheeseCake
到
ISnack
) 同时尝试调用应该是 逆变 的接口方法,或者实现更派生的类型 (CheeseCake
)。这种类型的双向变化在 C# 中是非法的。
因此,您基本上有两个选择。您可以在容器创建期间放弃协变,这允许您在实现中保持逆变,或者您可以在容器创建期间使用协变,但您将被迫在实现中强制转换为目标类型以满足接口。
前者具有逆变IWrapper<in TSnack>
定义:
CheeseCakeContainer wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<in TSnack> where TSnack : ISnack
{
void Wrap(TSnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(CheeseCake snack)
{
snack.Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}
后者:
IWrapper<ISnack> wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<out TSnack> where TSnack : ISnack
{
void Wrap(ISnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(ISnack snack)
{
((CheeseCake)snack).Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}
我有两个接口:
public interface ISnack { }
public interface IWrapper<TSnack> where TSnack : ISnack
{
void Wrap(TSnack snack);
}
还有两个类:
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
CheeseCake c;
public void Wrap(CheeseCake snack)
{
c = snack;
}
}
public class CheeseCake : ISnack { }
我要执行
IWrapper<ISnack> wrappedSnack = (IWrapper<ISnack>)(new CheeseCakeContainer());
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
但这会抛出一个无效的转换异常
System.InvalidCastException: 'Unable to cast object of type 'CheeseCakeContainer' to type 'IWrapper`1[ISnack]'.'
我应该更改什么才能使转换工作?我正在使用 C#9 和 .NET5
问题的症结在于您正在尝试创建一个 协变 的容器,或者您正在将更派生的类型分配给更通用的类型(CheeseCake
到
ISnack
) 同时尝试调用应该是 逆变 的接口方法,或者实现更派生的类型 (CheeseCake
)。这种类型的双向变化在 C# 中是非法的。
因此,您基本上有两个选择。您可以在容器创建期间放弃协变,这允许您在实现中保持逆变,或者您可以在容器创建期间使用协变,但您将被迫在实现中强制转换为目标类型以满足接口。
前者具有逆变IWrapper<in TSnack>
定义:
CheeseCakeContainer wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<in TSnack> where TSnack : ISnack
{
void Wrap(TSnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(CheeseCake snack)
{
snack.Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}
后者:
IWrapper<ISnack> wrappedSnack = new CheeseCakeContainer();
var c1 = new CheeseCake();
wrappedSnack.Wrap(c1);
public interface ISnack { }
public interface IWrapper<out TSnack> where TSnack : ISnack
{
void Wrap(ISnack snack);
}
public class CheeseCakeContainer : IWrapper<CheeseCake>
{
public void Wrap(ISnack snack)
{
((CheeseCake)snack).Type = "Strawberry";
}
}
public class CheeseCake : ISnack
{
public string Type { get; set; }
}