使用子类创建泛型

时间:2016-07-27 08:42:56

标签: c# generics

我正在尝试创建一种通用方法来保存我应该在给定类时搜索的属性。

我创建了以下结构来保存这些信息:

public struct Lookup<T> where T: BaseEntity
{            
    public Expression<Func<T, object>> Parent { get; set; }
}

然后创建了一个字典如下:

readonly Dictionary<string, Lookup<BaseEntity>> _dict =
    new Dictionary<string, Lookup<BaseEntity>>();

我有一个使用BaseEntity作为基类的类:

public class Agency : BaseEntity
{
    public int AgencyId { get; set; }
}

我使用以下信息创建一个新的Lookup结构:

new Lookup<Agency>
{
    Parent = x => x.Id
};

但如果我尝试将其添加到我的字典中,我会收到以下错误:

Cannot convert from Lookup<Agency> to Lookup<BaseEntity>

我原以为这会起作用,因为它们具有相同的基本类型,这是什么方式。

我有很多实体需要添加,所以希望一般都这样做,而不是必须做if / switch等。

由于

1 个答案:

答案 0 :(得分:3)

不,Agency不是BaseEntity的基本类型。 object DoSomething(T x) { ... } 派生自Lookup<BaseEntity>这一事实并不充分。但首先,让我们看看别的东西。

考虑通常的差异规则。您的方法对应

object DoSomething(BaseEntity x) { ... }

现在,在Agency中,这变为

BaseEntity

到目前为止,非常好 - 通过Agency代替BaseEntity完全合法,因为object DoSomething(Agency x) { ... } 来自BaseEntity。但是,的情况并非如此。你创建了这个:

Agency

显然,您无法通过Lookup<BaseEntity>代替public interface ILookup<out T> - 这会完全打破输入。与Java不同,C#(以及一般的.NET)泛型在编译时和运行时都是真实的,它们不会回退到ILookup<Agency>

此外,C#/ .NET限制了方差的使用。您可以在简单表达式和委托中免费获得差异,但不能在类或泛型类中获得。您需要明确您想要的方差类型,并使用接口。例如,在您的情况下,您可能会遇到以下情况:

ILookup<BaseEntity>

这样您就可以执行从TLookup<Agency>的演员表了。但是,对于你的情况来说这还不够,因为Expression在你的情况下是共同变体和反变体 - 换句话说,你不能向任何一个方向投射。

然而,这并不是什么大问题,因为你过度复杂化了一些事情。虽然您需要强大的输入来创建public sealed class Lookup { private readonly Expression parent; private Lookup(Expression parent) { this.parent = parent; } public Expression Parent { get { return parent; } } public static Lookup For<T>(Expression<Func<T, object>> member) where T : BaseEntity { return new Lookup(member); } } ,但您在类型本身中并不需要它 - 您无论如何都将使用无类型的{{1}}:

{{1}}