【问题标题】:Type parameter constraint that disregards generic type忽略泛型类型的类型参数约束
【发布时间】:2019-10-14 17:32:59
【问题描述】:

我有 EntityBase 抽象类,通常我的所有实体都继承自该类。它采用指定 Id 属性类型的泛型类型(例如 int 或 Guid)。 EntityBase 还包含一些逻辑来确定实体之间的相等性。

public abstract class EntityBase<T>
{
    public T Id { get; private set; }

    ...
}

在我的 .Net Core 2.2 Web 应用程序中,我使用的是 Asp.Net Identity,并且我有一个名为 ApplicationUser 的实体,它必须从 Microsoft.AspNetCore.Identity.IdentityUser 继承。因为不能从多个基类继承,所以不能从EntityBase继承。

所以,我创建了一个名为 IEntity 的接口,EntityBase 和 ApplicationUser 都实现了该接口

public interface IEntity<T>
{
    T Id { get; }
} 

我有一个 IRepository 接口,它的泛型类型必须是实体。我不在乎该实体上的 Id 类型是什么。我只想说 TEntity 只需要是一些 IEntity,我不在乎它是 IEntity 还是 IEntity。像下面这样的东西。这可能吗?

public interface IRepository<TEntity> where TEntity : IEntity
{
}

【问题讨论】:

  • IEntity 只是不存在的东西,你定义了 IEntity 这意味着,你总是必须提供一个类型参数。如果你想强制你的 TEntity 必须实现 IEntity,你只需要附加 ,但是要定义 T 是什么,你必须有接口 IRepository

标签: c# generics inheritance asp.net-identity


【解决方案1】:

限制IEntity&lt;T&gt; 的唯一方法是说:

public interface IRepository<TEntity, TId> where TEntity : IEntity<TId>
{
} 

您需要指定类型参数。如果您考虑一下,忽略IEntity&lt;T&gt; 中的T 的约束将毫无用处:您将无法使用Id 属性,因为您不知道它的类型,这是唯一的事情由IEntity&lt;T&gt;签约。

如果你说你不关心Id 的类型,那么你为什么关心那个东西是IEntity&lt;T&gt; 呢?

【讨论】:

    【解决方案2】:

    您可以创建一个没有参数的接口,所有实体都从该参数派生

    public interface IEntity
    {
    }
    public interface IEntity<out T> : IEntity
    {
        T Id { get; }
    }
    
    public abstract class EntityBase<T> : IEntity<T>
    {
        public T Id { get; private set; }
    }
    
    public interface IRepository<TEntity> where TEntity: IEntity
    {
    }
    

    【讨论】:

    • 这种空界面有什么用呢?执行的合同是什么?
    • 它只是一个基类,没有契约。所有实现Entity&lt;T&gt; 的类都继承自它,因此假定具有Id 属性。您无法从IEntity 读取属性,它必须通过每个实体的具体实现来完成。
    • 接口不是“基类”。据我所知,像IEntity 这样的空界面没有任何用途。您只是人为地使您的类型层次结构更加复杂。
    • @V0ldek - IEntity 只是所有实体的共同祖先。为了使用层次结构,如果不是object,您通常需要知道一个共同的祖先。这是 OOP 设计的要求,而 C# 没有办法在没有泛型说明符的情况下引用所有 IEntity&lt;&gt; 类型。
    • 但是为什么你需要所有实体的共同祖先? object 提供了每个 .NET 对象都必须拥有的方法。一个空的IEntity 接口提供了什么?将泛型类型约束到那个空接口有什么价值?这完全是人造的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    相关资源
    最近更新 更多