繁体   English   中英

c#类型推断 - 错误 - 没有隐式引用转换

[英]c# Type Inference - Error - There is no implicit reference conversion from

我有一个循环guid列表的方法,并通过DbContext将它们保存到数据库。 B是WebObjects的DbSet集合(例如: DbSet<MlaPerson> MlaPersons

protected void AddRelatedWebObject<A, B>(A mlaObject, B inputObject, List<Guid> guids) 
    where A : WebObject 
    where B : DbSet<WebObject>
{
    foreach (Guid guid in guids)
    {
        mlaObject.RelatedWebObjects.Add(inputObject.Find(guid));
        _db.SaveChanges();
    }
}

用法

foreach (ArticleRelationships item in articleRelationships)
{
    MlaArticle article = new MlaArticle();
    article = _db.MlaArticles.Include(m => m.WebSite).Where(m => m.Id == item.ArticleId).First();
    AddRelatedWebObject<MlaArticle, DbSet<MlaPerson>>(article, _db.MlaPersons, item.PersonIds);
}

_db.MlaPersons定义为

public class ECM2Context : DbContext
{
    public DbSet<MlaPerson> MlaPersons { get; set; }
}

和MlaPerson定义为

public class MlaPerson : WebObject, IValidatableObject
{
    ...
}

我认为通过推断B是DbSet<WebObject>会起作用,因为MlaPerson的基类是WebObject,但我错了。 我收到错误:

The type 'System.Data.Entity.DbSet<ExternalContentManager.Models.MlaPerson>' cannot be used as a type parameter 'B' in the generic type or method 'AddRelatedWebObjects'. There is not implicit reference conversion from 'System.Data.Entity.DbSet<ExternalContentManager.Models.MlaPerson>' to 'System.Data.Entity.DbSet<ExternalContentManager.Models.WebObject>'

我非常感谢所提供的任何和所有帮助。 谢谢你的帮助。

您正在制作一个常见的泛型错误 - 假设集合是协变的。 也就是说,即使汽车继承车辆, List<Car>的实例也不会从List<Vehicle>继承。 同样,即使MlaPerson继承自WebObject, DbSet<MlaPerson>也不会从DbSet<WebObject>继承。

你需要做的是这样的事情(我还没有测试过这段代码):

protected void AddRelatedWebObject<A, B, O>(A mlaObject, B inputObject, List<Guid> guids) 
    where A : WebObject 
    where B : DbSet<O>
    where O : WebObject
{
    foreach (Guid guid in guids)
    {
        mlaObject.RelatedWebObjects.Add(inputObject.Find(guid));
        _db.SaveChanges();
    }
}

并使用它:

foreach (ArticleRelationships item in articleRelationships)
{
    MlaArticle article = new MlaArticle();
    article = _db.MlaArticles.Include(m => m.WebSite).Where(m => m.Id == item.ArticleId).First();
    AddRelatedWebObject<MlaArticle, DbSet<MlaPerson>, MlaPerson>(article, _db.MlaPersons, item.PersonIds);
}

如果你这样做,你可能会放弃类型规范( <MlaArticle, DbSet<MlaPerson>, MlaPerson> ),因为它应该推断它。

DbSet<MlaPerson>不是DbSet<WebObject> ,因为MlaPerson派生自WebObject 在Stack Overflow上搜索“generic variance”以查找原因。

您可能希望更改方法参数和约束,如下所示:

protected void AddRelatedWebObject<A, B>(A mlaObject, DbSet<B> inputObject,
                                         List<Guid> guids) 
    where A : WebObject 
    where B : WebObject

然后像这样调用它:

AddRelatedWebObject<MlaArticle, MlaPerson>(article, _db.MlaPersons,
                                           item.PersonIds);

这可能有效 - 它甚至可以使用类型推断来实现:

AddRelatedWebObject(article, _db.MlaPersons, item.PersonIds);

建议您将类型参数重命名为TSourceTTarget ,以便更清楚,并遵循惯例。

--EDIT - 这个答案是错的。 看到更多信息的评论 -

向上转换不适用于容器(除非您正在向上转换数据结构,但这不是这种情况)。 想象一下下面的代码(为简单起见用数组编写,但同样的原则适用于所有通用容器):

class A{}
class B:A{}

/*Inside a method*/
B[] arrayB=new B[10];
A[] arrayA=arrayB;//This line will produce a compile error
arrayA[0]=new A();

现在arrayB[0]包含类型A的对象,即使它A不是派生的类的B 这就是为什么向上转换不适用于容器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM