我有我的基础接口类:
public interface IAlgorithm<T> where T : IParams
{
/// <summary>
/// Contains algorythm parameters
/// </summary>
T Params{ get; set; }
}
并且
public interface IParams
{
}
然后我有了算法实现的基本类:
public abstract class BaseAlgorithm<T> : IAlgorithm<T> where T: IParams
{
public virtual T Params { get; set; }
}
public class DataAlgorithm : BaseAlgorithm<IDataParams>
{
public override IDataParams Params { get; set; }
}
并且参数:
public interface IDataParams : IParams
{
}
有多个BaseAlgorithm
类实现。
现在我想创建DataAlgorith
的新isntance并将其分配给父接口:
IAlgorithm<IParams> algorithm = new DataAlgorithm();
但它不会工作并产生错误消息:
Cannot implicitly convert type 'DataAlgorithm' to 'IAlgorithm<IParams>'. An explicit conversion exists (are you missing a cast?)
以下代码可以正常使用:
IAlgorithm<IDataParams> algorithm = new DataAlgorithm();
如何分配父类型的任何想法?
答案 0 :(得分:3)
您不能这样做,因为DataAlgorithm
是IAlgorithm<IDataParams>
,而不是IAlgorithm<IParams>
。
想一想。如果是的话,你就能做到
IAlgorithm<IParams> algorithm = new DataAlgorithm();
algorithm.Params = ... some other kind of IParams but not IDataParams.
显然,这没有任何意义。
如果对象是IAlgorithm<IParams>
,则意味着您可以将实现IParams
的任何对象分配给其Params
属性。实现IAlgorithm<IDataParams>
的对象不是这种情况,因为它只接受IDataParams
setter中Params
的实现。因此,IAlgorithm<IDataParams>
不是IAlgorithm<IParams>
。
但是,如果不需要Params属性的setter,则可以使接口协变。
public interface IAlgorithm<out T> where T : IParams
{
/// <summary>
/// Contains algorythm parameters
/// </summary>
T Params{ get; }
}
相应地调整基类。
答案 1 :(得分:1)
要扩展Kris的上述答案check out the article on covariance and contravariance on MSDN。
为了简单起见,而不是IAlgorithm<IDataParams>
,想象一下List<IParams>
。任何实现IParams
的类型都应该能够存储在该列表中。但是,请想象以下代码:
List<IParams> lst = new List<IDataParams>();
lst.Add(new ClassImplementingIParamButNotIDataParams());
由于List<IDataParams>
只接受IDataParams
,后一种说法无效。但是,List<IDataParams> lst = new List<IParams>();
有效:可以添加到列表中的所有IDataParams
也将是IParams
。
这只是一个例子;正如Kris所说,您可以使用通用的in
和out
关键字来控制类型参数的协方差/逆变。 MSDN文章是一个良好的开端。