2

我正在尝试重构一种通过文件解析的方法。为了支持任意大小的文件,该方法使用了带有固定缓冲区的分块方法。

public int Parse()
{
    // Get the initial chunk of data
    ReadNextChunk();

    while (lengthOfDataInBuffer > 0)
    {
       [parse through contents of buffer]

       if (buffer_is_about_to_underflow)
          ReadNextChunk();
    }

    return result;
}

上面的伪代码是类中唯一的公共非静态方法的一部分(构造函数除外)。该类仅用于封装在解析文件时必须跟踪的状态。此外,一旦在类上调用了此方法,就不能/不应该再次调用它。所以使用模式是这样的:

var obj = new MyClass(filenameToParse);

var result = obj.Parse();

// Never use 'obj' instance again after this.

出于某种原因,这让我很烦。我可以将 MyClass 构造函数设为私有,将 Parse 更改为静态方法,并让 Parse 方法新建一个 Parse 范围为该方法的实例。这将产生如下使用模式:

var result = MyClass.Parse(filenameToParse);

MyClass 虽然不是静态类;我仍然需要在 Parse 方法中创建一个本地实例。

因为这个类只有两个方法;Parse 和(私有)ReadNextChunk,我想知道通过在 Parse 中嵌入 ReadNextChunk 逻辑作为匿名方法,将 Parse 编写为单个静态方法是否更简洁。状态的其余部分可以作为局部变量而不是成员变量进行跟踪。

当然,我可以通过将 ReadNextChunk 设为静态方法,然后传入所有上下文来完成类似的操作,但我记得 anon 方法可以访问外部范围。

这是奇怪和丑陋的,还是一种合理的方法?

4

3 回答 3

4

这可能更适合代码审查。

但是,这些是我对您的设计的评论:

  1. 我认为只使用一次的 obj 实例并不重要。如果您对它进行了窃听,有两种方法可以欺骗它:

    • 使用另一种方法,例如:

      public int Parse()
      {
          var obj = new MyClass(filenameToParse);
          return obj.Parse();
      }
      
    • 使MyClass实现 IDisposable 并将其包装在 using 语句中。我不推荐这样做,因为通常 IDisposable 在他们的Dispose()方法中有逻辑

  2. 我认为最好将您的MyClass接受参数Parse设置为Parse(string fileNameToParse). 它将MyClass作为一个服务类,使其无状态、可重用和可注入。

  3. 关于对静态类的影响。首先它在你的消费者和MyClass. 有时,如果您想在consumer不使用MyClass解析器的情况下测试/单元测试,将很难/不可能模拟MyClass成您想要的东西。

于 2013-07-10T01:40:31.340 回答
0

MyClass 虽然不是静态类;我仍然需要在 Parse 方法中创建一个本地实例。

您不需要静态类就可以利用静态方法。例如,这很好用:

public class MyClass
{
    public static string DoStuff(string input)
    {
        Console.WriteLine("Did stuff: " + input);
        return "Did stuff";
    }
}

public class Host
{
    public void Main()
    {
        MyClass.DoStuff("something");
    }
}
于 2013-07-10T05:47:26.893 回答
0

您只需要一个创建实例的静态解析方法,就像您在问题中建议的那样

public class MyClass
{
     // your existing code.... but make the members and constructor private.


     public static int Parse(string filenameToParse)
     {
         return new MyClass(filenameToParse).Parse();
     }
}

然后

就像你建议的那样使用它......

var result = MyClass.Parse(filenameToParse);
于 2013-07-10T03:59:06.833 回答