首页 > 解决方案 > 为什么这种隐式强制转换是不可能的?

问题描述

给定下面的类和接口,我想知道为什么隐式转换:

ISomeModelAbstract<IBasicModel> x = new ConcreteClass();

是不可能的。我试过了

public interface ISomeModelAbstract<out T> where T: IBasicModel

但后来我不能使用GetByIdGetAll方法。我感谢任何帮助或提示。谢谢你。

public interface IBasicModel {
    string _id { get; set; }
}

public class SomeModel: IBasicModel {
    public string _id { get; set; }

    /* some other properties! */
}

public interface ISomeModelAbstract<T> where T: IBasicModel
{
    bool Save(T model);
    T GetById(string id);
    IEnumerable<T> GetAll();
    bool Update(string id, T model);
    bool Delete(string id);
}

public abstract class SomeModelAbstract<T> : ISomeModelAbstract<T> where T : IBasicModel
{
    public bool Save(T model)
    {
        throw new System.NotImplementedException();
    }

    public T GetById(string id)
    {
        throw new System.NotImplementedException();
    }

    public IEnumerable<T> GetAll()
    {
        throw new System.NotImplementedException();
    }

    public bool Update(string id, T model)
    {
        throw new System.NotImplementedException();
    }

    public bool Delete(string id)
    {
        throw new System.NotImplementedException();
    }
}

public interface IConcreteClass: ISomeModelAbstract<SomeModel> { }

public class ConcreteClass: SomeModelAbstract<SomeModel>, IConcreteClass { }

标签: c#typesleast-common-ancestor

解决方案


由于协方差问题,这不起作用。考虑这个示例代码。

public class SomeModel2: IBasicModel {
    public string _id { get; set; }

    /* some other properties! */
}

之后,您可以将 SomeModel2 的某些对象传递给 x 的 Save 方法,显然,这是不行的。

    ISomeModelAbstract<IBasicModel> x = new ConcreteClass();
    var m = new SomeModel2();
    x.Save(m);

为了防止这种情况,您应该隐含地告诉您仅在返回(输出)位置使用泛型类型,而不是在输入中。例如:

public interface ISomeModelAbstract<out T> where T: IBasicModel

不幸的是,在这样做之后,您无法在 ISomeModelAbstract 界面中使用 Save and Update 方法。因为他们在参数(输入)的地方使用了 T。

有关更多信息,请参见以下链接:http ://tomasp.net/blog/variance-explained.aspx/


推荐阅读