.NET中的只读字段是否可以为空?

Rad*_*094 6 c# multithreading

我在多线程应用程序中有一个奇怪的错误:

public class MyClass
{
   private readonly Hashtable HashPrefs;
   public MyClass(int id)
  {
     HashPrefs = new Hashtable();
  } 

  public void SomeMethodCalledFromAnotherThread(string hashKey,string hashValue)
 {
    if (HashPrefs.Contains(hashKey))  // <-- throws NullReferenceException
    {

    }
 }
}
Run Code Online (Sandbox Code Playgroud)

一个主题是:

 SomeQueue.Add(new MyClass(1));
Run Code Online (Sandbox Code Playgroud)

而另一个线程做的是:

 SomeQueue.Dequeue().SomeMethodCalledFromAnotherThread(SomeClass.SomeMethod(),"const value"); 
Run Code Online (Sandbox Code Playgroud)

但是第二个线程如何在构造函数完成之前调用该方法?

编辑:我添加了带有函数参数的部分,因为它似乎可能是相关的.据我所知,传递的hashKey不能为null,因为SomeMethod()总是返回一个相关的字符串.

正如其他人所指出的,如果问题是传递给Contains()的null haskKey参数,则异常将是ArgumentNullException.

Mar*_*ell 11

反思是这样做的一种方式(SetField).

获得这种好奇心的第二种方法是,如果你过早地放弃引用,通过传递this(或者涉及隐式的sometihng this,例如捕获到匿名方法/ lambda中的字段).ctor:

public MyClass(int id)
{
    Program.Test(this); // oopsie ;-p
    HashPrefs = new Hashtable();
}
Run Code Online (Sandbox Code Playgroud)

或者更有可能(给出问题):

SomeQueue.Add(this);
Run Code Online (Sandbox Code Playgroud)

另一个相关问题可能是 - 它首先不能分配吗?答案是肯定的,特别是如果你使用序列化.与流行的看法相反,如果你有理由,你实际上可以绕过构造者; DataContractSerializer是这样做的一个很好的例子......

以下将MyClass使用null字段创建一个:

MyClass obj = (MyClass)
    System.Runtime.Serialization.FormatterServices.GetUninitializedObject(
        typeof(MyClass));
Run Code Online (Sandbox Code Playgroud)


And*_*are 7

是的,可以通过反射访问只读字段并更改其值.所以你的问题的答案是肯定的,这是可能的.

然而,还有许多其他事情也可能为您创造问题.多线程代码难以编写,并且可能出现的问题难以诊断.


作为旁注,你确定你没有得到一个ArgumentNullException吗?如果somekeynull,该Hashtable.Contains方法将抛出一个ArgumentNullException.也许这就是问题?