我打算从开发选择、代码评审和针对定义的环境(开发、测试、生产等)的一般测试的角度出发。我将使用C#作为主要的编码参考。
我想要的是:
详细信息:
最近,在日志记录相当差的WebForms应用程序中,在代码更改后,我遇到了一个“类型初始化'X‘抛出异常”错误。异常来自的类看起来类似于以下内容:
public class someModelClass
{
private static string someConnection = new someConnectionStringRequester().GetConnection(someParam1, someParam2, ...); // <- this was the primary change. someConnectionStringRequester is not a static class/doesn't have static methods
//some public properties
public static List<someModelClass> getInstancesOfModel(someParam1, someParam2, ...)
{
//return some list of models based on someConnection
}
}还有其他几个“模型”类,它们遵循相同的模式,差别很小。
在最初的测试(开发和测试环境)中,应用程序没有遇到任何异常。一旦部署到生产环境中,它就会启动异常。在更改之前,我做了两件事,检查了代码,并添加了一些更好的日志记录。这个类以前是这样的:
public class someModelClass
{
private static string someConnection = someOtherConnectionStringRequester.GetConnection(someParam1, someParam2, ...); // <- this was the original compared the the primary change above. someOtherConnectionStringRequester was a static class/had static methods
//some public properties
public static List<someModelClass> getInstancesOfModel(someParam1, someParam2, ...)
{
//return some list of models based on someConnection
}
}在进行日志记录之后,我不得不强制执行一个异常,以确保我能够得到更多的细节。我使用GetConnection方法“抛出新异常(‘testMessage’)”。如前所述,有多个“模型”类看起来像这个类,但是强制异常抛出了一个不同的类抛出类型初始化程序异常,这个类在抛出异常的初始类之前被调用。这个不同的类看起来如下:
public class someDifferentModelClass
{
private static string someConnection = new someConnectionStringRequester().GetConnection(someParam1, someParam2, ...); // <- this also had a similar change
//some public properties
public void someAction()
{
someConnectionStringRequester someOtherConnection = new someConnectionStringRequester();
// do some work based on someOtherConnection
getInstancesOfModel(someParam1, someParam2, ...)
// do some other work
}
private static List<someModelClass> getInstancesOfModel(someParam1, someParam2, ...)
{
//return some list of models based on someConnection
}
}这似乎指向了类第一次调用时、私有静态变量被调用时或两者混合的问题。
如果有任何信息需要澄清或添加才能理解上述内容,请告诉我。
发布于 2020-12-21 20:00:06
使用静态初始化时,您将放弃对初始化顺序的任何显式控制。如果事情成功,原因如下之一:
在您的场景中用来工作的初始化更像是一个意外,尽管它符合语言规范:旧类大概有一个静态构造函数,因此确实保证在调用构造函数之前初始化它的静态字段。现在,您的类没有静态构造函数,因此不能保证按不同的顺序初始化不同的静态变量。有关参考,请参见关于堆栈溢出的问题:C#中静态类初始化的顺序是确定的吗?
一种可能的解决方案是将初始化推迟到运行时,即在第一次访问属性时延迟建立连接。这并不能防止所有潜在的问题(例如,它可能导致循环依赖的无限递归),但它通常确保正确的初始化顺序。这种方法的另一个问题是,在访问属性之前,错误不会变得明显:我们将此代码从初始化时推迟到运行时。
还有一个原因,为什么应该在运行时执行尽可能多的初始化:您的代码(例如,在Main()中)可以在初始化之前执行安装程序。这也极大地帮助了可调试器。
正确地进行初始化是一个非常困难的问题。在C++中出现几个分段错误之后,我学到了避免静态初始化的经验,但是C#也遇到了同样的问题:任何依赖于特定静态初始化顺序的代码都会中断。
有更优雅的方法可用于初始化。
https://softwareengineering.stackexchange.com/questions/420222
复制相似问题