C# c语言中的子级到父级泛型转换#
我有我的基本接口类:C# c语言中的子级到父级泛型转换#,c#,generics,covariance,contravariance,C#,Generics,Covariance,Contravariance,我有我的基本接口类: public interface IAlgorithm<T> where T : IParams { /// <summary> /// Contains algorythm parameters /// </summary> T Params{ get; set; } } 然后我有了算法实现的基本类: public abstract class BaseAlgori
public interface IAlgorithm<T> where T : IParams
{
/// <summary>
/// Contains algorythm parameters
/// </summary>
T Params{ get; set; }
}
然后我有了算法实现的基本类:
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; }
}
有多种BaseAlgorithm
类实现
现在我想创建DataAlgorith
的新实例,并将其分配给父接口:
IAlgorithm<IParams> algorithm = new DataAlgorithm();
IAlgorithm algorithm=new DataAlgorithm();
但它不起作用并产生错误消息:
Cannot implicitly convert type 'DataAlgorithm' to 'IAlgorithm<IParams>'. An explicit conversion exists (are you missing a cast?)
无法将类型“DataAlgorithm”隐式转换为“IAlgorithm”。存在显式转换(是否缺少强制转换?)
下面的代码可以正常工作:
IAlgorithm<IDataParams> algorithm = new DataAlgorithm();
IAlgorithm algorithm=new DataAlgorithm();
您知道如何分配给父类型吗?您不能这样做,因为
DataAlgorithm
是IAlgorithm
,而不是IAlgorithm
想想看。如果是的话,你就能做到
IAlgorithm<IParams> algorithm = new DataAlgorithm();
algorithm.Params = ... some other kind of IParams but not IDataParams.
相应地调整基类。您不能这样做,因为
DataAlgorithm
是IAlgorithm
,而不是IAlgorithm
想想看。如果是的话,你就能做到
IAlgorithm<IParams> algorithm = new DataAlgorithm();
algorithm.Params = ... some other kind of IParams but not IDataParams.
相应地调整您的基类。要扩展上面Kris的答案 要使其简单,而不是一个
IAlgorithm
,请想象一个列表
。实现iParms
的任何类型都应该能够存储在该列表中。但是,请想象以下代码:
List<IParams> lst = new List<IDataParams>();
lst.Add(new ClassImplementingIParamButNotIDataParams());
List lst=new List();
添加(新的ClassImplementingIParamButNotIDataParams());
由于List
仅接受IDataParams
,后一条语句将无效。但是,List lst=new List()代码>有效:可以添加到列表中的所有IDataParams
也将是iParms
这只是一个例子;正如Kris所说,您可以使用泛型上的in
和out
关键字控制类型参数的协方差/逆变。MSDN文章是一个很好的开始。要扩展上面Kris的答案
要使其简单,而不是一个IAlgorithm
,请想象一个列表
。实现iParms
的任何类型都应该能够存储在该列表中。但是,请想象以下代码:
List<IParams> lst = new List<IDataParams>();
lst.Add(new ClassImplementingIParamButNotIDataParams());
List lst=new List();
添加(新的ClassImplementingIParamButNotIDataParams());
由于List
仅接受IDataParams
,后一条语句将无效。但是,List lst=new List()代码>有效:可以添加到列表中的所有IDataParams
也将是iParms
这只是一个例子;正如Kris所说,您可以使用泛型上的in
和out
关键字控制类型参数的协方差/逆变。MSDN文章是一个很好的开始。但是从技术上讲,DataAlgorithm
是IAlgorithm,因为DataAlgorithm是IAlgorithm,IDataParams是iParms。我是说,我希望它能以这种方式工作。谢谢你的样品,我会试试。@makambi不,不是。这就是我在回答的前半部分试图解释的。但从技术上讲,DataAlgorithm
是IAlgorithm,因为DataAlgorithm是IAlgorithm,而IDataParams是iParms。我是说,我希望它能以这种方式工作。谢谢你的样品,我会试试。@makambi不,不是。这就是我在回答的前半部分试图解释的代码>无效<代码>列表
不是逆变的。只有接口可以是协变或逆变的,类不能。无效的原因很简单:lst.First()的类型是什么?由于lst是List
类型的变量,因此它必须是实现IDataParams
的变量。但是如果新列表()
被分配给lst
,则无法保证这一点。非常完整:一个List
可以分配给List
类型的变量,当且仅当T==U.List lst=new List()代码>无效<代码>列表
不是逆变的。只有接口可以是协变或逆变的,类不能。无效的原因很简单:lst.First()的类型是什么?由于lst是List
类型的变量,因此它必须是实现IDataParams
的变量。但是如果新列表()
被分配给lst
,则无法保证这一点。非常完整:一个列表
可以分配给列表
类型的变量,当且仅当T==U时。
List<IParams> lst = new List<IDataParams>();
lst.Add(new ClassImplementingIParamButNotIDataParams());