I have a strange bug in a multithreaded app:
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
{
}
}
}
One thread does the :
SomeQueue.Add(new MyClass(1));
And another thread does the :
SomeQueue.Dequeue().SomeMethodCalledFromAnotherThread(SomeClass.SomeMethod(),"const value");
But how can the second thread call the method before the constructor is finished?
Edit: I added the part with the function parameters, as it seems this might be relevant. As far as I can tell, the hashKey being passed on cannot be null, as SomeMethod() always returns a relevant string.
As others have pointed out,if the problem was a null haskKey parameter passed to the Contains() , the exception would be ArgumentNullException.
Use the readonly keyword in C# This means that the variable or object can be assigned a value at the class scope or in a constructor only. You cannot change the value or reassign a value to a readonly variable or object in any other method except the constructor.
If it's private and readonly , the benefit is that you can't inadvertently change it from another part of that class after it is initialized. The readonly modifier ensures the field can only be given a value during its initialization or in its class constructor.
In C#, you can use a readonly keyword to declare a readonly variable. This readonly keyword shows that you can assign the variable only when you declare a variable or in a constructor of the same class in which it is declared.
readonly keyword is used to define a variable which can be assigned once after declaration either during declaration or in constructor. const keyword is used to define a constant to be used in the program. Following is the valid usage of a readonly and const keywords in C#.
Reflection is one way to do this (SetField
).
A second way to get this curiosity is if you give away the reference too early, by passing this
(or sometihng involving an implicit this
, such as a field captured into an anonymous method / lambda) out of the .ctor
:
public MyClass(int id)
{
Program.Test(this); // oopsie ;-p
HashPrefs = new Hashtable();
}
Or more likely (given the question):
SomeQueue.Add(this);
Another relevant question might be - can it not be assigned in the first place? And the answer to that is yes, especially if you are using serialization. Contrary to popular belief, you can actually bypass the constructors, if you have a reason; DataContractSerializer
is a good example of something that does this...
The following will create a MyClass
with a null field:
MyClass obj = (MyClass)
System.Runtime.Serialization.FormatterServices.GetUninitializedObject(
typeof(MyClass));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With