I need to create a collection of ConcreteProviderX instances to execute LINQ operators on it. I prefer to use struct for ConcreteArgumentsX types, but casting to base interface IArguments while creating an array causes the compile-time error: The type 'IArguments' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'ICommandProvider' (Code = CS0453). I have an alternative implementation with class instead of struct for ConcreteArgumentsX types, but it causes a run-time System.InvalidCastException (Unable to cast "SetProvider" to "ICommandProvider"). How the error would be solving for the case with struct and for the case with 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()
};
}
}
}