在.Net中创建对象是否昂贵?

Chr*_*old 13 .net class-design code-design

我刚刚重构了一个同事的代码,粗略地看起来像这样......

public class Utility
  public void AddHistoryEntry(int userID, HistoryType Historytype, int companyID)
  {
    // Do something...
  }
  public void AddHistoryEntry(int userID, HistoryType historyType, int companyID, string notes)
  {
    // Do something...
  }
}
Run Code Online (Sandbox Code Playgroud)

对此......

public class HistoryEntry
{
  public long UserID { get; private set; }
  public HistoryType HistoryType { get; private set; }
  public long CompanyID { get; set; }
  public string Notes { get; set; }

  public HistoryEntry(long userID, HistoryType historyType)
  {
    this.UserID = userID;
    this.HistoryType = historyType;
  }
}

public class Utility
{
  public void AddHistoryEntry(HistoryEntry entry)
  {
    // Do something...
  }
}
Run Code Online (Sandbox Code Playgroud)

}

现在,这是更好的代码设计,并且是Bob叔叔的最爱.但是,我的同事辩称,每次我们想要调用这种方法时,新建一个对象要贵得多.

他是对的吗?

进一步说明

感谢到目前为止的所有回复.为了简洁,我遗漏了许多细节,但其中一些细节已经引起了答案的问题.

  • 实用程序类不存在.我只是想把这些方法放在一个类中供大家看.实际上它是一个明智的阶级.
  • 事实上,原始代码中有5个AddHistoryEntry方法.所有这些都需要很多int参数.重构的一个原因是,AddHistory(0, 1, 45, 3);并没有真正告诉你太多!
  • AddHistoryEntry不是从紧密循环中调用的,但它在整个应用程序中被广泛使用.

更正

我现在更新了代码示例,因为我对一些参数犯了错误.

Kal*_*see 20

如果你同时在内存中有数百万个这样的对象,他可能是正确的.但如果你不这样做,那么他提出的几乎肯定是一个有争议的问题.始终首先选择更好的设计,然后仅在您不满足性能要求时才进行修改.


Jon*_*eet 16

创建一个新对象非常便宜.你必须在一个非常紧密的循环中创建很多对象以注意到任何差异......但与此同时,它并不是免费的.您还需要记住,成本是隐藏的一半 - 您在创建对象时预先花费一些成本,但这也意味着垃圾收集器还有更多工作要做.

那么更清洁的设计是否值得追求性能?我们无法告诉您 - 这取决于您的代码的使用方式.我强烈怀疑性能损失是微不足道的,但是如果你在紧密循环使用它,它可能不是.现在只有一种方法可以找到:如果你担心,可以测量一下.就个人而言,我可能只是去寻求更清洁的设计,只有当它看起来成为一个问题时才检查性能.

(如果该方法是打磁盘或数据库,顺便说一下,该差异几乎必然会是不显着).

顺便提一句,一个建议是:你的HistoryEntry类型实际上需要是可变的吗?您是否可以将所有属性设置为只读,由私有只读变量支持?

只是提到威尔的观点 - 我有点同意他的观点.如果这两种方法是你需要这个概念的唯一地方,我完全不确定是否值得为它创建一个新类型.不是因为性能方面,而是因为你引入了额外的一堆代码而没有明显的好处.这里的关键词被证明 - 如果你实际上在其他地方使用相同的参数集合,或者可以有用地将逻辑放入HistoryEntry类中,那完全是另一回事.

编辑:只是回应关于多个整数参数的观点--C#4将允许命名参数,这应该使这更容易.所以你可以打电话:

AddHistoryEntry(userId: 1, companyId: 10);
Run Code Online (Sandbox Code Playgroud)

使用附加类使名称可见需要以下之一:

  • 来自C#4的命名构造函数参数(在这种情况下,你不比使用该方法更好)
  • 可变类型(urgh - 可能导致难以追踪原始版本中不存在的错误)
  • 用于构造实例的长静态方法名称("FromUserAndCompanyId"),这些实例变得难以处理,具有更多参数
  • 可变的构建器类型
  • 一堆"With"方法:new HistoryEntry().WithCompanyId(...).WithUserId(...)- 这使得在编译时更难以验证您提供了所有必需的值.

  • 我的妻子一直在读我的肩膀并问'干什么意味着什么?'.无价. (3认同)

Bro*_*oam 5

为什么不在类本身中使用静态方法?

public static void AddHistoryEntry(HistoryEntry entry)

为您保存实用程序类.新对象可能很昂贵,但可能不是 - 但它可能并不重要.良好的默认值允许您更轻松地扩展代码,并且您将比在性能方面节省更多的维护时间,除非您在循环中执行此操作.


小智 5

你们都错了,但是他比您错了。

  • 好的,我可以看到它的到来,所以我会更加清楚。为了进行重构,您正在重构(显示),而他过早地进行了优化。 (3认同)
  • @jon我知道,它在答案中更合适。但是,出于实际原因,我中的画家拒绝破坏优美的回应(眼睛,情人)。可以用很多方法来阅读它,因此激发了您思考他人代码路径的含义的想法。或者其他的东西。 (3认同)
  • 您知道@chris只是在代码冰山一角。似乎确实没有意义……但是我不得不说毫无意义的重构是我的罪恶感之一。 (2认同)