当我需要一些项目时,我应该只使用它的“int id”吗?

时间:2012-08-12 17:34:58

标签: c# oop

我的应用程序有InstrumentFactory - 我创建Instrument实例的唯一地方。每个工具实例都包含多个字段,例如Ticker=MSFTGateId=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

我应该这样做吗?将Instrument改为instrumentId将使其成为一项艰难的要求(每个工具应该只有一个唯一的ID)。但是我会有什么好处?作为“硬性要求”的回报,我想为此获得一些好处......(速度,可读性?)但我没有看到它们。

5 个答案:

答案 0 :(得分:4)

在任何地方使用ID代替对象都是错误的方法,这违背了OOP的精神。

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

  1. 这是类型安全的。您不会意外地将Person之类的内容传递给第一个版本,但您可能会意外地将person.Id传递给第二个版本。
  2. 它使您的代码易于修改。如果您将来确定需要long ID或其他方式来识别唯一的Instrument,则无需更改主叫代码。
  3. 你应该更改你的字典,它应该像Dictionary<Instrument, InstrumentInfo>,而不是Dictionary<int, InstrumentInfo>,就像你现在一样。这样,您也可以获得两种优势。要使其有效,您需要在Instrument中实现相等性,这意味着正确覆盖Equals()GetHashCode(),理想情况下还要实施IEquatable<Instrument>

答案 1 :(得分:1)

在对象方面工作总是比整数这样的原始值更好。如果明天您的要求发生变化并且您需要的不仅仅是ID,那么很容易将其添加到Instrument对象而不是更改所有代码。

答案 2 :(得分:1)

GetInstrumentInfo(int instrumentId);

这可能意味着客户端代码必须具有:

GetInstrumentInfo(instrument.Id);

不要让您的方法的用户担心这样的小细节。让他们只传递整个对象,让你的方法完成工作。

看不出任何重大的性能劣势。无论是传递Int还是引用实际对象。

假设您想要更多地开发GetInstrumentInfo,它更容易访问整个对象而不仅仅是Int。

答案 3 :(得分:1)

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

“如果我有两个ID == 53的乐器,那么这是否意味着它们绝对是同一乐器,无论如何?或者是否有一个有意义的案例,它们可能会有所不同?”

假设答案是“它们都是相同的。如果任何其他属性不同,那就是一个错误,或者因为一个这样的对象是在另一个之后获得的,并且很快就会自行解决(当任何处理线程使用时)旧仪器,停止使用它)“然后:

首先,在内部,只需使用你发现的任何东西。您很可能会发现这一直是int,尽管您通过坚持将Instrument传递给该方法获得了一些类型安全性。如果所有Instrument构造都发生在通过工厂方法访问的internalprivate构造函数中,并且代码的用户无法创建伪造{{1} id与系统中的任何内容都不匹配。

如此定义相等:

Instrument

现在,特别是当我们考虑到上述内容很可能在大多数情况下被内联时,关于我们是否在相等性方面使用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;
  }
}

或者:

public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
    return instrumentInfos[instrument];
}

或者:

public InstrumentInfo GetInstrumentInfo(Instrument instrument)
{
    return instrumentInfos[instrument.Id];
}

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

由于在内部使用仪器本身不会再花费你的成本,我仍然建议你这样做(上面三个选项中的第一个)作为类型安全并且难以通过然后,伪造的值也将适用于您的内部代码。另一方面,如果你发现一组调用仍然只使用id(例如,他们正在与只有ID意味着什么的数据库层交谈),那么改变这些地方对你来说变得快捷方便,隐藏在用户之外。

您还可以让您的用户使用您的对象作为键,并进行快速的相等比较(如果适合他们的话)。

答案 4 :(得分:-1)

你可以重载每个函数,一个拿一个乐器,一个拿一个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的任何地方将其更改为传递ID时,当前代码仍将起作用。

至于你是否“应该”纯粹取决于你。您需要权衡更改它所需的时间与在代码中进行更改的好处。