C#静态对象引用

c# static object reference

我有一个class像这样

public class FileLogger
{
   public FileLogger(string typeOfLog)
   {
    //implementation
   }

   public void LogError(string err)
   {
    //implementation
   }

   public void LogMessage(string err)
   {
    //implementation
   }
}

由于这是应用程序将其输出记录到文件的日志记录 class,因此人们会期望它是静态的 class。然而,如您所见,事实并非如此。然而,它在应用程序中是这样使用的:

public class BugetApplication 
{
     private static FileLogger logger;

    //constructor
    public BugetApplicationClass()
    {
       logger = new FileLogger("some-constructor-parameter"); 
    }

    //a method that uses the FileLogger class for logging
    public string Classify()
    {
        try
        {
           //start multiple threads for classification
           Classification clsf = new Classification();
           clsf.handleEvent += clsf_handleEvent;
           clsf.Classify(); 
        }
        catch (Exception exp)
        {
           logger.LogError(exp.Message);
        }
    }

    private static void clsf_handleEvent(string errString)
    {
       if(errString.Contains("error"))
       {
          logger.LogError(errString);
       }
    } 

}

多线程由 BugetApplication class 的 classify 方法启动。 class 中的任何错误都会触发在 BugetApplication class 的 clsf_handleEvent 方法中处理的事件。所以多个线程可以各自触发自己的事件。在 BugetApplication class 中将实例变量创建为静态变量是否会产生任何影响,或者将其保持为非静态是否具有相同的效果?我不希望任何一个线程覆盖另一个线程的错误消息。

编辑 只是为了清除问题,仅创建一次的 BugetApplication class 有一个静态变量 'static FileLogger logger; ' 它在其构造函数中创建了一个实例,将一些值传递给 FileLogger [=25 的构造函数=].在 BugetApplication class 中,有一个方法调用分类 class 的 classify 方法。 Classify 方法启动各种线程,并在出现任何错误时触发一个事件,该事件在 BugetApplication class 中处理,因此此 clsf_handleEvent 方法可以对其进行多次调用。

为什么您认为它会覆盖另一个线程的错误消息?记录器应该只附加消息,所以不应该有任何覆盖(虽然取决于你如何处理日志记录)。但是有一个潜在的问题 - 根据您的日志记录功能,您可能会阻止对该文件的访问。因为该方法适用于外部文件,所以您应该在函数中使用 lock

class 是否是静态的并不重要,问题是并发访问外部资源需要同步多线程才能成为线程安全的。

lock documentation on msdn

这真的取决于记录器的实际实现。 静态 classes 现在不受欢迎,因为它们使单元测试更加困难。许多传统上作为静态或单例实现的设施(记录器、电子邮件等)现在提供单元 test/IoC 友好的替代方案(例如工厂和接口或虚拟 class)。

这些设施的设计通常是客户端应用程序用来交互的前端 class 和负责同步和实际日志记录(或电子邮件,或其他)的异步后端。

关键在于前端是否多线程。

如果他们不是;你应该为每个线程创建一个新的。在这种情况下,记录器可能必须是局部变量或使用它的方法的参数。

然而,通常它们是多线程和可重入的,因为它们所做的只是将日志消息传递到后端并且没有自己的状态。在这种情况下,它们可以保存为静态变量或应用程序范围的单例,但最好在 IoC 容器中将它们实例化为单例并使用它们将其注入 classes。这样做可以使使用模拟记录器编写单元测试变得容易得多。