Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 此代码中的类型检查是否有代码气味?_C#_Oop_Typechecking - Fatal编程技术网

C# 此代码中的类型检查是否有代码气味?

C# 此代码中的类型检查是否有代码气味?,c#,oop,typechecking,C#,Oop,Typechecking,我有一个界面“IPartyCountService”,它统计客户和供应商的数量 实现类“PartyCountService”使用类型检查来检查该方是客户还是供应商 实现类PartyCountService使用类型检查时是否发出代码气味 任何反馈、评论、批评都将不胜感激 public interface IPartyCountService { int GetTotalNumberOfCustomers(); int GetTotalNumberOfSuppliers(); }

我有一个界面“IPartyCountService”,它统计客户和供应商的数量

实现类“PartyCountService”使用类型检查来检查该方是客户还是供应商

实现类PartyCountService使用类型检查时是否发出代码气味

任何反馈、评论、批评都将不胜感激

public interface IPartyCountService
{
    int GetTotalNumberOfCustomers();
    int GetTotalNumberOfSuppliers();
}

internal class PartyCountService:IPartyCountService
{
    IPartyRepository _partyRepository;

    public PartyCountService(IPartyRepository partyRepository)
    {
        _partyRepository = partyRepository;
    }

    public int GetTotalNumberOfCustomers()
    {
        var counter = 0;
        foreach(var customer in _partyRepository.GetAll())
        {
            if (customer is Customer) counter++;
        }
        return counter;
    }

    public int GetTotalNumberOfSuppliers()
    {
        var counter = 0;
        foreach (var customer in _partyRepository.GetAll())
        {
            if (customer is Supplier) counter++;
        }
        return counter;
    }
}

public interface IPartyRepository
{
    IList<IParty> GetAll();
}
internal class PartyRepository:IPartyRepository
{
    public IList<IParty> GetAll()
    {
        // put together all parties, including customers and suppliers
        return allParties;
    }
}
internal class Customer:IParty{}
internal class Supplier:IParty{}
public interface IParty{}
公共接口IPartyCountService
{
int getTotalNumber of Customers();
int getTotalNumber of Suppliers();
}
内部类PartyCountService:IPartyCountService
{
IPartyRepository\u partyRepository;
公共PartyCountService(IPartyRepository partyRepository)
{
_partyRepository=partyRepository;
}
public int getTotalNumber of Customers()
{
var计数器=0;
foreach(var customer在_partyRepository.GetAll()中)
{
如果(客户是客户)计数器++;
}
返回计数器;
}
public int getTotalNumber of Suppliers()
{
var计数器=0;
foreach(var customer在_partyRepository.GetAll()中)
{
如果(客户是供应商)计数器++;
}
返回计数器;
}
}
公共接口IPartyRepository
{
IList GetAll();
}
内部类PartyRepository:IPartyRepository
{
公共IList GetAll()
{
//将所有各方(包括客户和供应商)放在一起
归还各方;
}
}
内部类客户:IParty{}
内部类供应商:IParty{}
公共接口IParty{}

我觉得这不合适,但您可以做一点小小的改变

return _partyRepository.GetAll().Count(p => p is Customer);
我将使用.OfType扩展方法

return _partyRepository.GetAll().OfType<Customer>().Count();
return\u partyRepository.GetAll().OfType().Count();

编辑:正如下面SP所述,这会使代码更干净,但不一定能解决问题。

也许IParty应该有一种方法,在计算“客户”时询问您感兴趣的任何东西?

这有点臭,但不是我见过的(或我自己做过的)最臭的事情。有几点想法:

  • 是否有理由将供应商和客户存储在同一个集合中?如果你发现你的代码总是与众不同,那么重构你存储它们的方式
  • 存储一组接口,然后将其转换为具体类型,这会让它产生异味。每当我看到这种类型的转换时,我马上就会想到抽象泄漏或静态结构需要重新审视
  • 如果将它们结合起来确实有意义的话,LINQ可以让这变得更简单一些
像这样:

return _partyRepository.GetAll().OfType<Supplier>().Count();
return\u partyRepository.GetAll().OfType().Count();

首先,我认为这是一个选择的问题。您必须了解每个可能的备选方案所涉及的权衡:

  • 你的
  • 在基类上创建一个字段,使您能够知道哪种类型的参与方
  • 备选方案(1)的优点是更加简洁,并且具有更友好的OO方法。(但是,请记住,在查看对象的具体类型时,您正在破坏多态性。)

    备选方案(2)的优点是,首先,您不依赖元数据来了解对象类型。其次,
    is
    调用比检查变量类型更昂贵。因此,请确保你能接受这场演出


    编辑:现在我来看一下,您将抽象为一种接口类型,然后将其转换回具体类型。为什么呢?如果使用集合的类知道不同的类型,它应该直接访问存储在那里的类型

    我认为您不应该对公共API隐藏
    客户
    供应商
    。但是,建议使用
    ICustomer
    ISupplier
    接口替换它们。以下基于组件前沿(即其公共API)设计的接口将帮助您自然地实现更好的设计


    关于类型检查和计数:我不认为显式动态类型检查是坏事。然而,通过使用接口,它们将在语义上变得更加自然。另外,我不认为为了保存一个显式的
    foreach
    和一对
    {}

    客户和供应商存储在partyRepository中的一个异构集合中,应该到处引入类似LINQ的语句?似乎仅仅依靠一个客户集合和一个单独的供应商集合要容易得多;然后它可以公开诸如GetCustomers()、GetSuppliers()或Get()之类的函数


    使用这种方法,您仍然可以实现GetAll()——将两个集合“联合”在一起非常容易。比过滤出异类集合更容易(性能可能更好)。

    我想是的。。。为什么不在将客户/供应商添加到集合中时对其进行记录?为什么不从
    \u partyRepository
    中仅检索
    x
    类型的类型,而不是调用
    GetAll()
    ?此外,它看起来可能有一个泛型
    存储库
    类可以从中重构。如果我想快速回答这些问题,我应该停止在VS中检查语法,以获取类似的简单内容:但它仍在检查类型,那么代码本身是否有味道?你是说检查类型不正确吗?感谢优化的代码。@SP-在理想情况下,面向对象永远不应该在运行时执行类型检查。当然,现实是完全不同的。还请记住,我的建议是对简单性的改进,而不是对性能的改进。@SP-另外,我的回答中的最后一行只是简单地表示我对ORM工具的厌恶。事实上,让我把它去掉。这听起来很有趣。你能举个例子吗?我有点迷路了。我不确定你到底在尝试什么