4

当我从带有调试器 (F5) 的 Visual Studio 内部启动它时,我的应用程序运行良好。但是,当我在没有附加调试器(Ctrl-F5 或启动 .exe 文件)的情况下启动应用程序时,我确实总是得到一个StackOverflowException幸运地记录在 Windows 事件日志中的结果。

有问题的代码如下:

namespace Caliburn.Micro.Contrib
{
    public static class FrameworkExtensions
    {
        public static class ViewLocator
        {
            static readonly Func<string,object, IEnumerable<string>> _baseTransformName = Micro.ViewLocator.TransformName;

            public static void EnableContextFallback()
            {
                Caliburn.Micro.ViewLocator.TransformName = FallbackNameTransform;
            }    

            static IEnumerable<string> FallbackNameTransform(string typeName, object context)
            {
                var names = _baseTransformName(typeName, context);
                if (context != null)
                {
                    names = names.Union(_baseTransformName(typeName, null));
                }

                return names;
            }
        }
    }
}

FrameworkExtensions.EnableContextFallack()在 App 启动期间调用了该方法,并且在第一次调用Caliburn.Micro.ViewLocator.TransformName. 这意味着_baseTransformName变量在没有附加调试器时被调用之后被初始化,而在调试器被附加时被调用 之前被初始化。EnableContextFallback() EnableContextFallback()

能够通过添加静态构造函数并在构造函数中分配变量来修复错误

namespace Caliburn.Micro.Contrib
{
    public static class FrameworkExtensions
    {
        public static class ViewLocator
        {
            static readonly Func<string, object, IEnumerable<string>> _baseTransformName;

            static ViewLocator()
            {
                 _baseTransformName = Micro.ViewLocator.TransformName;
            }

            public static void EnableContextFallback()
            {
                Caliburn.Micro.ViewLocator.TransformName = FallbackNameTransform;
            }    

            static IEnumerable<string> FallbackNameTransform(string typeName, object context)
            {
                var names = _baseTransformName(typeName, context);
                if (context != null)
                {
                    names = names.Union(_baseTransformName(typeName, null));
                }

                return names;
            }
        }
    }
}

这确保变量_baseTransformName总是在第一次调用之前设置EnableContextFallback()

所以问题是:为什么在附加调试器时静态变量有不同的初始化行为,有没有办法“禁用”不同的行为?

干杯

4

1 回答 1

1

所以问题是:为什么在附加调试器时静态变量有不同的初始化行为,有没有办法“禁用”不同的行为?

当没有静态构造函数时,很少能保证静态变量初始化器的行为。事实上,您甚至可以在不调用静态变量初始化器的情况下创建类的实例!当您使用调试器时,CLR 会以不同的方式执行各种操作(尤其是围绕 JITting)。

使用静态构造函数可能是为您提供更可预测的初始化行为的最佳方式。

有关更多信息,请参阅我关于 .NET 4 中类型初始化更改的博文

于 2012-04-30T14:45:25.873 回答