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());