记录一个C#静态变量的问题

9 篇文章 0 订阅

本来想写一个日志类,初始化是获取streamwriter,然后记录日志时write,flush,这样可以避免重复打开文件,可是streamwriter莫名其妙变成null了,于是写了一个简单的测试demo

using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;

namespace ConsoleApp1
{
    class Tmp
    {
        public Tmp()
        {
            System.Console.WriteLine("tmp construct");
        }

        ~Tmp()
        {
            System.Console.WriteLine("~tmp");
        }
    }

    class Handle
    {
        private static Handle h = new Handle();
        private static Tmp t = null;
        private static int a = getA();

        public Handle()
        {
            System.Console.WriteLine("Handle construct");
            t = new Tmp();
        }

        public static Tmp getTmp()
        {
            return t;
        }

        public static int getA()
        {
            System.Console.WriteLine("getA");
            return 1;
        }
        
        ~Handle()
        {
            System.Console.WriteLine("~Handle");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine("Main");
            if (null == Handle.getTmp())
            {
                System.Console.WriteLine("t is null");
            }
            else
            {
                System.Console.WriteLine("t not null");
            }

            System.Console.Read();
        }
    }
}

输出如下

Main
Handle construct
tmp construct
getA
t is null

System.Console.Read();生效前Tmp的构造函数发生了,但是没有经过析构函数就莫名其妙变成null,

Handle的构造函数发生在Main输出之后,此输出是Handle的静态变量h初始化时发生的,因为初始化是赋值为new Handle();

Tmp构造函数是在Handle的构造函数中调用的,唯一赋值null的地方在初始化时,

 

于是得出以下结论:

1.静态变量不是立即初始化,而是在第一次调用时初始化,因为Main输出在Handle construct之前,

2.静态变量按顺序初始化,如上打印,Handle construct在getA之前

3.静态变量一次初始化所有,如上并没有使用Handle的静态变量a,但是经过了a的初始化getA()

 

从以上三个结论可以再次推导出t为什么是null,

Handle的静态变量初始化时,Handle中将t也初始化了,

而第二个变量也就是t作为第二变量初始化为null,便与Handle构造函数中的赋值冲突,将t又重置为null了

 

也就是说,变量还是一开始都在的,只是都是空的,并没有初始化。这种情况下只需要把有使用其他变量的初始化函数放到最后面即可,或者干脆全部赋值为null,0;然后在需要初始化的地方初始化

        private static Tmp t = null;
        private static int a = getA();
        private static Handle h = new Handle();
        //private static Handle h = null;

换个顺序,t先被赋值为null,new Handle()发生时,Handle的构造函数中初始化时t被第二次赋值

于是输出:

Main
getA
Handle construct
tmp construct
t not null

最好变量定义时全部赋值为空,null,0,然后统一再次赋值或修改,这样就不会发生这种问题了,不过发生这种问题,然后把问题找出来也是个乐趣。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值