C# 当我需要一些物品时,我是否应该使用它的;int id";相反

C# 当我需要一些物品时,我是否应该使用它的;int id";相反,c#,oop,C#,Oop,我的应用程序有InstrumentFactory——我唯一创建Instrument实例的地方。每个仪器实例包含多个字段,例如Ticker=MSFT和GateId=1,以及唯一的Id=1 现在我意识到我几乎不需要Instrument实例。在90%的情况下,我只需要Id。例如,我现在有这样的方法: public InstrumentInfo GetInstrumentInfo(Instrument instrument) { return instrumentInfos[instrument

我的应用程序有
InstrumentFactory
——我唯一创建
Instrument
实例的地方。每个仪器实例包含多个字段,例如
Ticker=MSFT
GateId=1
,以及唯一的
Id=1

现在我意识到我几乎不需要
Instrument
实例。在90%的情况下,我只需要
Id
。例如,我现在有这样的方法:

public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
    return instrumentInfos[instrument.Id];
}
我们知道,我们不应该传递超过要求的更多信息。因此,此代码可能应该重构为:

public InstrumentInfo GetInstrumentInfo(int instrumentId)
{
    return instrumentInfos[instrumentId];
}
我90%的代码现在可以重构为使用
instrumentId
而不是
Instrument


我应该那样做吗?将所有位置的
仪器
更改为
仪器id
将成为一项硬要求(每个仪器都应该有一个唯一的id)。但我有什么好处呢?作为“硬性要求”的回报,我想从中得到一些好处。。。(速度,可读性?)。如果明天您的需求发生变化,并且您需要的不仅仅是ID,那么很容易将其添加到
工具
对象中,而不是更改所有代码。

在任何地方使用ID而不是对象都是错误的方法,这与OOP的精神背道而驰

使用对象本身有两大优势:

  • 这是类型安全的。您不能意外地将
    Person
    之类的内容传递给第一个版本,但可以意外地将
    Person.Id
    传递给第二个版本
  • 它使您的代码易于修改。如果将来您决定需要
    long
    id,或以其他方式识别唯一的
    仪器
    ,则无需更改调用代码

  • 你可能也应该改变你的字典,它应该是类似于
    字典
    ,而不是像你现在这样的
    字典
    。这样,您也可以同时获得这两个优势。要使其工作,您需要在
    Instrument
    中实现相等,这意味着正确地重写
    Equals()
    GetHashCode()
    ,理想情况下还可以实现
    IEquatable

    您可以重载每个函数,一个使用仪器,一个使用id:

    public InstrumentInfo GetInstrumentInfo(Instrument instrument)
    {
        // call GetInstrumentInfo passing the id of the object
        return GetInstrumentInfo[instrument.Id];
    }
    
    public InstrumentInfo GetInstrumentInfo(int instrumentId)
    {
        return instrumentInfos[instrumentId];
    }
    
    这将为您提供足够的灵活性,以便在您通过调用
    GetInstrumentInfo
    将其更改为pass id的任何位置时,当前代码仍能正常工作

    至于你是否“应该”完全取决于你自己。您必须权衡更改代码所需的时间和更改代码的好处

    GetInstrumentInfo(int instrumentId);
    
    这可能意味着客户端代码必须具有:

    GetInstrumentInfo(instrument.Id);
    
    不要让您的方法的用户担心这样的小细节。让它们只传递整个对象,并让您的方法完成工作

    没有发现任何重大性能劣势。是否将Int或引用传递给实际对象


    假设您想进一步开发GetInstrumentInfo,那么访问整个对象比只访问Int更容易。

    您需要问自己的第一件事是:

    “如果我有两个ID==53的工具,那么这是否意味着无论发生什么情况,它们都绝对是同一个工具?或者是否存在一种有意义的情况,它们可能不同?”

    假设答案是“它们都是相同的。如果任何其他属性不同,要么是一个bug,要么是因为一个这样的对象被一个接一个地获取,并且很快就会自行解决(当任何处理线程都在使用旧仪器时,停止使用它)”,那么:

    首先,在内部,只要使用你觉得更方便的东西。您很可能会发现这一直都是通过
    int
    实现的,尽管您坚持将
    工具
    传递给该方法会获得某种类型安全性。如果所有
    仪器
    构造都是通过工厂方法访问的
    内部
    私有
    构造函数进行的,并且代码用户无法使用与系统中任何内容都不匹配的id创建假
    仪器
    ,则尤其如此

    平等的定义如下:

    public class Instrument : IEquatable<Instrument>
    {
      /* all the useful stuff you already have */
      public bool Equals(Instrument other)
      {
        return other != null && Id == other.Id;
      }
      public override bool Equals(object other)
      {
        return Equals(other as Instrument);
      }
      public override int GetHashCode()
      {
        return Id;
      }
    }
    
    或:

    或:

    无论您选择哪一种,性能影响都是相同的。提供给用户的代码将是类型安全的,并保证他们不会传递虚假的值。选择的实现可以是由于其他原因而更方便的实现

    由于在内部使用仪器本身作为键不会花费更多的成本,我仍然建议您这样做(上面三个选项中的第一个),因为类型安全性和难以传递虚假值也将应用于您的内部代码。另一方面,如果您发现一组调用仍然只使用id(例如,如果它们正在与一个只有id表示任何意义的数据库层进行通信),则仅更改这些位置对您来说将变得快速而简单,并且对用户隐藏


    您还可以让用户将对象用作键,并在适合的情况下进行快速相等比较。

    我不使用字典。出于性能原因,我使用数组。所以我通过
    int
    索引访问它。这些性能原因是真的吗?您应该首先编写干净的代码,如果结果显示它太慢(如评测所示),则对其进行优化。这就是为什么我有id。我需要很多“仪器到某物”的映射。起初我用了很多字典。拥有
    id
    我现在可以只使用
    数组
    。这是非常方便的,因为应用程序需要花费大量的时间通过仪器访问某些内容。如果您确定数组和字典之间的差异对您很重要,您可以创建一个自定义的
    IDictionary
    ,它
    public InstrumentInfo GetInstrumentInfo(Instrument instrument)
    {
        return instrumentInfos[instrument];
    }
    
    public InstrumentInfo GetInstrumentInfo(Instrument instrument)
    {
        return instrumentInfos[instrument.Id];
    }
    
    public InstrumentInfo GetInstrumentInfo(Instrument instrument)
    {
        return GetInstrumentInfo(instrument.Id);
    }
    private InstrumentInfo GetInstrumentInfo(int instrumentID)
    {
        return instrumentInfos[instrumentID]
    }