【问题标题】:Use an anonymous method to avoid creating a single-use object?使用匿名方法来避免创建一次性对象?
【发布时间】:2013-07-07 19:19:13
【问题描述】:

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

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 方法可以访问外部范围。

这是怪异难看,还是合理的做法?

【问题讨论】:

  • 为什么不用匿名 TYPE?
  • 如果方法是静态的,那么你将如何为它编写单元测试呢?您将文件系统与解析器紧密耦合。
  • @Romoku 与您为任何其他方法编写单元测试的方式相同。只是使用静态方法更难模拟它,如果没有理由模拟它,那不是问题。我会说创建一个实际上不保持任何有用状态的实例将是设计缺陷。如果方法不需要任何状态,它应该是静态的。此外,标题具有误导性。问题的正文中没有关于匿名的任何内容,它只是一个静态与实例问题。
  • @Servy 他说他可以把ReadNextChunk变成一个匿名方法。
  • 这是来自 ScriptCS 的 class,我认为这与您的问题相似。

标签: c# delegates anonymous-function anonymous-methods


【解决方案1】:

这可能更适合代码审查。

但是,这些是我对你的设计的看法:

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

    • 使用其他方法,例如:

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

  2. 我认为最好让你的MyClass 接受ParseParse(string fileNameToParse) 中的参数。它将MyClass作为服务类,使其无状态、可重用和可注入。

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

【讨论】:

    【解决方案2】:

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

    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);
    

    【讨论】:

      【解决方案3】:

      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");
          }
      }
      

      【讨论】:

      • 我了解静态方法。我的观点是我仍在使用类的实例(在静态方法中)来跟踪状态。我的问题是是否有一种优雅的方式来调用静态方法中的代码块,其中该代码可以访问调用方法中的局部变量。
      • 为什么不也有一个私有静态方法,它将您要访问的变量作为附加参数,并让公共的调用私有的?
      猜你喜欢
      • 2016-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多