【发布时间】:2020-03-17 20:55:41
【问题描述】:
我需要创建一个 ConcreteProviderX 实例的集合以在其上执行 LINQ 运算符。我更喜欢将 struct 用于 ConcreteArgumentsX 类型,但在创建数组时强制转换为基本接口 IArguments 会导致编译时错误:类型“IArguments”必须是不可为空的值类型才能将其用作参数“T”泛型类型或方法“ICommandProvider”(代码 = CS0453)。对于 ConcreteArgumentsX 类型,我有一个使用类而不是结构的替代实现,但它会导致运行时 System.InvalidCastException(无法将“SetProvider”转换为“ICommandProvider”)。对于 struct 和 class 的情况,错误将如何解决?
namespace ErrorUsingStructForConcreteArgumentsX
{
interface ICommandProvider<T> where T : struct, IArguments
{
void F(string command, out T? arguments);
}
class ConcreteProvider1 : ICommandProvider<ConcreteArguments1>
{
public void F(string command, out ConcreteArguments1? arguments) { arguments = null; /* other code */ }
}
class ConcreteProvider2 : ICommandProvider<ConcreteArguments2>
{
public void F(string command, out ConcreteArguments2? arguments) { arguments = null; /* other code */ }
}
interface IArguments { }
struct ConcreteArguments1 : IArguments { /* some value type properties */ }
struct ConcreteArguments2 : IArguments { /* some value type properties */ }
class Program
{
static void Main(string[] args)
{
ICommandProvider<ConcreteArguments1> provider = new ConcreteProvider1(); // ok
// compile-time error
var providers = new ICommandProvider<IArguments>[]
{
(ICommandProvider<IArguments>)new ConcreteProvider1(),
(ICommandProvider<IArguments>)new ConcreteProvider2()
};
}
}
}
namespace AlternativeUsingClassForConcreteArgumentsX
{
interface ICommandProvider<IArguments>
{
void F(string command, out IArguments arguments);
}
class ConcreteProvider1 : ICommandProvider<ConcreteArguments1>
{
public void F(string command, out ConcreteArguments1 arguments) { arguments = null; /* other code */ }
}
class ConcreteProvider2 : ICommandProvider<ConcreteArguments2>
{
public void F(string command, out ConcreteArguments2 arguments) { arguments = null; /* other code */ }
}
interface IArguments { }
class ConcreteArguments1 : IArguments { /* some value type properties */ }
class ConcreteArguments2 : IArguments { /* some value type properties */ }
class Program
{
static void Main(string[] args)
{
ICommandProvider<ConcreteArguments1> provider = new ConcreteProvider1(); // ok
// runtime error
var providers = new ICommandProvider<IArguments>[]
{
(ICommandProvider<IArguments>)new ConcreteProvider1(),
(ICommandProvider<IArguments>)new ConcreteProvider2()
};
}
}
}
【问题讨论】:
-
你有一个不变的泛型声明,因此你得到一个错误。
out参数不允许您有变体声明。你应该使用精确的类型声明,比如ICommandProvider<ConcreteArguments1> provider = new ConcreteProvider1(); -
请查看此线程以获取解释和可能的解决方法Why do C# out generic type parameters violate covariance?
-
请看我更新的答案。我添加了代码进行测试。欢迎提出任何问题
-
@PavelAnikhouski 感谢您的评论。请你展示一下代码应该是这样的吗?这对我们真的很有帮助。