创建新实例或只设置内部变量

时间:2009-04-13 16:38:27

标签: c# .net asp.net optimization class

我编写了一个辅助类,它在构造函数中接受一个字符串,并提供了许多Get属性来返回字符串的各个方面。目前设置该行的唯一方法是通过构造函数,一旦设置它就无法更改。由于这个类只有一个内部变量(字符串),我想知道我是否应该保持这种方式,还是应该允许设置字符串呢?

一些示例代码我的帮助为什么我要问:

StreamReader stream = new StreamReader("ScannedFile.dat");
ScannerLine line = null;
int responses = 0;
while (!stream.EndOfStream)
{
  line = new ScannerLine(stream.ReadLine());
  if (line.IsValid && !line.IsKey && line.HasResponses)
    responses++;
}

以上是计算给定扫描文件中有效响应数量的快速示例。这样编码会更有利吗?

StreamReader stream = new StreamReader("ScannedFile.dat");
ScannerLine line = new ScannerLine();
int responses = 0;
while (!stream.EndOfStream)
{
  line.RawLine = stream.ReadLine();
  if (line.IsValid && !line.IsKey && line.HasResponses)
    responses++;
}

此代码用于ASP.net Web应用程序的后端,需要稍微响应。我知道这可能是一个过早优化的情况,但我正在为客户端的响应性和可维护性进行编码。

谢谢!

编辑 - 我决定也包括该类的构造函数(是的,这就是它的真实含义。):

public class ScannerLine
{
  private string line;
  public ScannerLine(string line)
  {
    this.line = line;
  }

  /// <summary>Gets the date the exam was scanned.</summary>
  public DateTime ScanDate
  {
    get
    {
      DateTime test = DateTime.MinValue;
      DateTime.TryParseExact(line.Substring(12, 6).Trim(), "MMddyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out test);
      return test;
    }
  }

  /// <summary>Gets a value indicating whether to use raw scoring.</summary>
  public bool UseRaw { get { return (line.Substring(112, 1) == "R" ? true : false); } }

  /// <summary>Gets the raw points per question.</summary>
  public float RawPoints
  {
    get
    {
      float test = float.MinValue;
      float.TryParse(line.Substring(113, 4).Insert(2, "."), out test);
      return test;
    }
  }
}

**编辑2 - **我包含了该类的一些示例属性以帮助澄清。正如您所看到的,该类从扫描程序中获取一个固定的字符串,并且可以更容易地将该行拆分为更有用的块。该文件是Scantron机器的行分隔文件,解析它的唯一方法是一堆string.Substring调用和转换。

6 个答案:

答案 0 :(得分:4)

如果你真的需要这个课,我肯定会坚持使用不可变版本。不变性使您更容易推理您的代码 - 如果您存储对ScannerLine的引用,那么知道它不会改变是有用的。性能几乎肯定是微不足道的 - 读取线路所涉及的IO可能比创建新对象更重要。如果您真的关注性能,那么在决定根据这些性能问题做出设计决策之前,应该对代码进行基准测试/分析。

但是,如果您的状态只是一个字符串,那么您是否真的提供了直接存储字符串并使用适当的方法来分析它们的好处? ScannerLine是否分析字符串并缓存该分析,或者它只是一堆解析方法?

答案 1 :(得分:0)

你的第一个方法是更清楚。表现明智,你可以获得一些东西,但我认为不值得。

答案 2 :(得分:0)

我会选择第二种选择。它更有效率,而且它们同样易于理解IMO。另外,您可能无法知道将在while循环中调用这些语句的次数。谁知道呢?它可能是0.01%的性能提升,或50%的性能提升(不太可能,但可能)!

答案 3 :(得分:0)

不可变类有很多优点。像这样的简单值类是不可变的是有意义的。对于现代VM,类的对象创建时间很短。你拥有它的方式很好。

答案 4 :(得分:0)

我实际上完全抛弃了类的“实例”性质,并将其用作静态类,而不是像现在这样的实例。每个属性完全相互独立,除了使用的字符串。如果这些属性彼此相关,和/或每次分配字符串时都设置了其他“隐藏”变量(例如预处理属性),那么就有理由这样做方式或其他方式重新分配,但从你在那里做的,我将它改为100%静态方法的类。

如果你坚持让类成为一个实例,那么出于纯粹的性能原因我会允许重新分配字符串,因为CLR不会不断地创建和销毁同一个类的实例(除了字符串本身显然)。

在一天结束时,由于没有其他类实例变量,因此您可以以任何方式实现IMO。可能有风格的原因要做一个或另一个,但解决这个问题时很难“错”。如果类中有其他变量在构造时设置,那么这将是一个完全不同的问题,但是现在,您可以看到最清晰的代码。

答案 5 :(得分:0)

我会选择你的第一个选择。在你的例子中,没有理由让这个类变得可变。保持简单,除非你真的需要使它变得可变。如果您真的关心性能,那么运行一些性能分析测试,看看有什么不同。