【问题标题】:Static variables is reset to null after a while静态变量在一段时间后重置为 null
【发布时间】:2013-12-13 14:28:13
【问题描述】:

我有一个static member,它是一个列表,它似乎有时会出于某种原因重置为null(可能是在未捕获的异常之后)。 这是我的代码:

public abstract partial class MyClass
{
            private static List<MyClass> Types;

            static MyClass()
            {
                Types = new List<MyClass>();
                Types.Add(new Myclass(0));
                Types.Add(new Myclass(1));
            }


            public static MyClass GetMyClass(int id)
            {                
                return Types.Single(x => x.id == id);
            }
}

GetMyClass 方法随后将触发 null 引用异常。 在我的代码中,我没有将此成员设置为null。 你有什么想法吗?

如果有帮助,这里是完整的代码:

public partial class TestRequest
{
    public abstract partial class TrType
    {
        private static List<TrType> Types;

        static TrType()
        {
            Types = new List<TrType>();
            Types.Add(TrType.Real.Instance);
            Types.Add(TrType.Template.Instance);
        }
        protected int idTrType;

        public static TrType GetTrType(int id)
        {
            return Types.Single(x => x.idTrType == id);
        }

        public int IdTrType
        {
            get { return idTrType; }
            set { idTrType = value; }
        }

        public abstract void Launch(TestRequest tr);
    }
}

// In another file.

public partial class TestRequest
{
    public partial class TrType
    {
        public class Real : TestRequest.TrType
        {
            private static Real instance;
            public const int ID = 1;

            protected Real()
            {
                idTrType = ID;
            }

            static Real()
            {
                instance = new Real();
            }

            public static Real Instance
            {
                get { return instance; }
                set { instance = value; }
            }

            public override void Launch(TestRequest tr)
            {
                // do something
            }
        }
    }
}

【问题讨论】:

  • 您是否曾经将null 元素添加到Types?这是我看到它发生的唯一方式。
  • 不,我插入元素的唯一位置是在这个静态构造函数中。
  • 好的,那么id属性的get是如何实现的呢?这是我在这里看到的最后一个可能抛出 NRE 的地方(假设那是实际抛出的)。

标签: c# list constructor static


【解决方案1】:

我相信您因为Single 而遇到了异常。 (它不是 NRE)

Single(IEnumerable) 方法抛出异常 如果输入序列为空。而是在输入时返回 null 序列为空,使用 SingleOrDefault。

试试:

 return Types.SingleOrDefault(x => x.id == id);

如果没有找到,它将返回 null。但是,如果在id 中找到多个项目,您仍然会遇到异常

【讨论】:

  • Types 为 null 时发生异常,而不是我在参数中提供不正确的 id 时发生异常。
  • @user3099700,你确定你没有在任何地方清除列表?
  • @user3099700,只是在声明的时候实例化它,而不是静态构造函数,private static List&lt;MyClass&gt; Types = new List&lt;MyClass&gt;();我不确定这会不会有什么效果,但试一试
  • 聪明,但这个答案没有解决 NRE。 OP 明确表示他正在接受 NRE。根据 MSDN,Single 不会抛出这种类型的异常。
【解决方案2】:

我不知道为什么它会被重置为 null。如何将其设置为只读,以便只能在静态构造函数中设置并且永远不会更改。不过,列表可以稍后修改。

    public abstract partial class MyClass
    {
        private static readonly List Types;

        static MyClass()
        {
            Types = new List<MyClass>();
            Types.Add(new Myclass(0));
            Types.Add(new Myclass(1));
        }


        public static MyClass GetMyClass(int id)
        {
            return Types.Single(x => x.id == id);
        }
    }

【讨论】:

  • 是的,readonly 应该在重新分配列表时产生编译时错误。但是它不会阻止例如所有元素都不会被删除。
  • @StuartLC - 空参数不会引发 NRE。这是一个很好的答案 +1。
  • 我会记住这个解决方案,但我怀疑它不会改变任何东西。我已经三重检查了,我从不在其他任何地方分配这个列表。
  • 如果您担心列表稍后会更改,您可以切换到只读集合。私有静态只读 ReadOnlyCollection 类型;然后在静态构造函数的最后:Types = list.AsReadOnly()
【解决方案3】:

问题可能在于您没有向我们显示的代码。可以通过将变量设置为只读来解决此静态私有变量上的 NRE。

仔细看有几个问题:

  1. 这是一个部分类。这很可能意味着示例中遗漏了某些内容并导致了问题。可访问性是私有的,因此该变量只能由包含类设​​置为 null。 OP 中没有显示任何内容会导致变量“重置为 null”。但是,将变量标记为只读(使类不可变)将解决这种类型的运行时错误并避免由类的其他成员引起的副作用。

  2. Types.Add(newMyclass(0)); 存在大小写问题。我认为这只是一个类型-o,而不是尚未解释的设计问题(例如继承)。

  3. 我们没有x.id 的定义。它可能是一个新类,它可能是部分的扩展(我们需要确定#2 的答案)。如果x.id 可以为空并且x 为空,那么这将导致NRE。 请注意,如果Types 为空,您将不会收到 NRE,如果 Types 为空,您将收到

【讨论】:

  • 确实,我没有把我所有的代码,但其他部分无关紧要。大小写问题也是一个错字,因为我真正的班级实际上不是“MyClass”:)
  • @user3099700 - 即便如此,考虑到变量的可访问性,可能出错的选项是有限的。如第 1 点和第 3 点所述。
【解决方案4】:

好的,我终于可以重现该问题了。 我从一开始就错了。 NRE 是在 Linq 表达式中引起的:

Types.Single(x => x.id == id);

“x”将为空(不是我认为的类型),这可能在我首先访问“真实”实例时发生(在 TrType 初始化之前)。在这种情况下,“Real”的静态构造函数被调用以实例化“instance”属性。由于“Real”继承自“TrType”,“TrType”的静态构造函数被调用,“Types”列表构造开始。然后它尝试插入仍在实例化过程中的“Real”实例,因此当时仍为空。然后我们在列表中有一个“空”对象...

感谢大家的参与。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多