gpt4 book ai didi

c# - 接口(interface)作为一个用于继承的原因,而不是实现者

转载 作者:行者123 更新时间:2023-11-30 22:51:32 28 4
gpt4 key购买 nike

.NET 中的接口(interface)实际上被编译成类,纯抽象类,唯一的区别是它有interface 前缀。所以一般来说,接口(interface)的任何实现者都是该接口(interface)的继承者,而不是很多书上写的实现者。是的,我知道接口(interface)在企业代码中有另一个用途——为不相关的类提供通用功能。但是对于 MSIL 来说,任何类实际上都是接口(interface)的子类型。它给出了仅使用简单的具体类扩展接口(interface)的理由,而不是创建基接口(interface)的另一个派生接口(interface)。因此,当某些客户端引用了该接口(interface)并且需要向下转换为更具体的实体时,开发人员会创建另一个派生接口(interface)并将其向下转换。为什么他们不直接向下转换为具体的派生类,因为它实际上是接口(interface)的有效子类型?示例代码:

public inteface IEntity
{
int Id { get; set; }
}

public class Vote : IEntity
{
public int Id { get; set; }

public int SubjectId { get; set; }

public bool Sign { get; set;}

public int UserId {get; set;}

public void Validate()
{
if (UserId == default)
throw new Exception("UserId is not defined");
if (SubjectId == default)
throw new Exception("SubjectId is not defined");
}
}

public abstract class BusinessEngine
{
private readonly IRepository _repo;

public void Save(IEntity entity)
{
BeforeSave(entity);
DoSave(entity); // omit code, it just delegates work to repository
AfterSave();
}

protected virtual void BeforeSave(IEntity entity)
{
}

protected virtual void AfterSave(IEntity entity)
{
}
}

public class VotesBE: BusinessEngine
{
protected override void BeforeSave(IEntity entity)
{
var vote = entity as Vote;
vote.Validate();
}
}

但许多开发人员更愿意为 IEntity 创建另一个派生接口(interface) - 例如,将扩展基本 IEntity 接口(interface)的 IValidatableEntity 并且他们会在 BusinessEngine 的代码中做这件事:

`public abstract class BusinessEngine
{
private readonly IRepository _repo;

public void Save(IEntity entity)
{
BeforeSave(entity);
DoSave(entity); // omit code, it just delegates work to repository
AfterSave();
}

protected virtual void BeforeSave(IEntity entity)
{
if (entity is IValidatableEntity ve)
ve.Validate();
}

protected virtual void AfterSave(IEntity entity)
{
}
}`

最佳答案

您描述的两种技术都是有效的,但是您提出的技术可能会通过 Generics 实现.

例如:

public abstract class BusinessEngine<TEntity> where TEntity : IEntity
{
private readonly IRepository _repo;

public void Save(TEntity entity)
{
var typedEntity = entity as TEntity;

BeforeSave(entity);
DoSave(entity);
AfterSave();
}

protected virtual void BeforeSave(TEntity entity) { }

protected virtual void AfterSave(TEntity entity) { }
}
public class VoteBusinessEngine : BusinessEngine<Vote>
{
protected override void BeforeSave(Vote entity)
{
vote.Validate();
}
}

现在,回到您最初的问题“为什么要用一种方式而不是另一种方式?”这取决于您的目标和需求。

如果您的目标是编写可以处理多种类型实体的通用服务(或服务集合),您可能需要使用 IValidatableEntity 方法。在这种情况下,您可以让实体通过实现额外的接口(interface)来描述它们的能力。

如果您希望在不修改实体本身的情况下为少数实体类型向单个服务添加特殊情况处理,那么通用方法很有意义。

真正归结为:您希望谁“拥有”这种特殊行为?实体还是服务?

如果您想更深入,请阅读 Role InterfacesInterface Segregation Principle (SOLID 中的“我”)。

关于c# - 接口(interface)作为一个用于继承的原因,而不是实现者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59090132/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com