-2

I have the following code:

public class Settings
{
    private object _lock = new object();
    public void Save() {
        lock (_lock)
        {
        ...
        }
    }
}

On windows 8 x86 / .net 4.0 lock throws exception:

Exception Type:        System.ArgumentNullException
Exception Message:     Value cannot be null.
Exception Target Site: ReliableEnter 

I attached debugger and its null. _lock is really null :|

On windows 7 x64 it works all right. I am checking other OSes now.

EDIT:

It is realted to deserialization. After deserialization of Settings class _lock is null. _lock field didn't exist at the time of serilization of settings and its getting back deserialized as null. Deleting serilized object file and recreating it with lock field eliminated exception. I will check if this is correct deserialization behavior if field didin't exist at serialization. Overwriting object value initialized in declaration doesn't look cool to me. But thats pretty much answer to this. I admit that I didn't consider serialization, deserialization at the time I asked for help ;).

EDIT2: Here is the code that ilustrates my scenario and what was happening to me:

  1. Serilize class without _lock field

    class Program
    {
        static void Main(string[] args)
        {
            Settings set = new Settings();
    
            using (FileStream fs = new FileStream(@"C:\test\tst.set", FileMode.Create, FileAccess.Write, FileShare.None))
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fs, set);
                fs.Flush();
                fs.Close();
            }
        }
    }
    
    [Serializable]
    internal class Settings
    {
        private int _i = 12;
    
    
        public void testMethod()
        {
    
            int i = 0;
            i++;
            Console.WriteLine(i);
    
        }
    }
    
  2. Deserialize to class with lock field and call testMethod:

    class Program
    {
        static void Main(string[] args)
        {
            Settings set = null;
            using (FileStream fs = new FileStream(@"C:\test\tst.set", FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                BinaryFormatter bf = new BinaryFormatter();
                set = (Settings)bf.Deserialize(fs);
                fs.Flush();
                fs.Close();
            }
    
            set.testMethod();
        }
    }
    
    [Serializable]
    internal class Settings
    {
        private int _i = 12;
        private readonly object _lock = new object();
    
        public void testMethod()
        {
            lock (_lock)
            {
                int i = 0;
                i++;
                Console.WriteLine(i);
            }
        }
    }
    

program will crash on testMethod call.

I didin't find anything related to this behavior in documentaion. I will check for null after deserialization and that will end my trouble.

Ok. How deserilization can assign null to my readonly field assigned on declaration?

Velja Radenkovic
  • 716
  • 1
  • 6
  • 27
  • 3
    Please provide a short but *complete* program demonstrating the problem. – Jon Skeet Mar 16 '15 at 11:10
  • 3
    First thing to check is anywhere you reassign the `_lock` to null? Mark the field as `readonly`. Compiler will yell at you if you do. If not, *provide a short but complete program* as @JonSkeet is asking. – Sriram Sakthivel Mar 16 '15 at 11:11
  • This is what I have time for at this moment. Screen recording: http://screencast.com/t/xiU73MrSy I will try to build minimal case as soon as I get some time. – Velja Radenkovic Mar 16 '15 at 11:12
  • Done readonly. It was originaly readonly. No other references to _lock. – Velja Radenkovic Mar 16 '15 at 11:13
  • mmm. Object instance which behaves is created by deserialization. Let me try to build something that reproduces. – Velja Radenkovic Mar 16 '15 at 11:20
  • Minimal test case is above so is solution to my problem. Thanks guys and sorry for wasting your time with uncomplete question. The reason why it didin't behave on win 7 / x64 was that it had no old settings / seriaized file. – Velja Radenkovic Mar 16 '15 at 13:41
  • OK. I am bringing this question up again. Please review the edited question and especially last line. – Velja Radenkovic Mar 16 '15 at 13:46

2 Answers2

0

To all intents and purposes, if you set it to a new Object and you don't change it anywhere else, then what you're seeing is impossible.

First thing I'd try is to move the new Object code into my constructor, if it's happy there, then leave it be. Either way, trace over the assignment and see if it ever got assigned.

Make sure your IDE is not watching anything that could effect the value of the variable as a side effect - check conditional breakpoints for the same thing.

Note that you can create a conditional break point on change!

If still broken add asserts, compile in debug - run outside of the IDE.

If the debug version crashes when the IDE is not part of the mix, take it to other PCs and try it.

If it works on other PCs, Virus scan/reinstall etc. Memory check etc.

The compiler could be broken, try reinstalling Visual Studio.

Then I'm out of ideas!

Mark Rabjohn
  • 1,643
  • 14
  • 30
  • I would appreciate if you look at my edited question. Especially the last edit and last lines. – Velja Radenkovic Mar 16 '15 at 13:52
  • The only other thing that I can think of is using the [NotSerialized] attribute on _lock. – Mark Rabjohn Mar 18 '15 at 13:07
  • It doesn't work. Sets it to null with nonserilized attr and crashes with same error. You can try only last isolated cases with NonSerializable attr. They are compile ready. My thinking until this instance was: Since you have to provide empty constructor (or leave without any so compiler creates one empty) for class to be serializable, I was thinking that deserialization creates instance of class by constructing it and after that it sets its fields to serialized values. I was under impression that it shouldn't do that for read-only fields. But now I don't have a clue. – Velja Radenkovic Mar 18 '15 at 13:38
  • BTW this is optional tech talk now. I solved my problem as soon as I figured out whats happening by setting lock to new object() after deserialization. – Velja Radenkovic Mar 18 '15 at 13:57
-2

Private properties are not serialized by default. If you want them to be serialized you need to create your custom serializer methods.

You can look at the following question for extra details

Community
  • 1
  • 1
Juan
  • 3,675
  • 20
  • 34
  • No I dont want them to be serialized. Is there anyone that would want lock serialized? its readonly field. How deserialization sets it to null? Or how on deserilization its not assigned with declaration assignment. private readonly object _lock = new object(); – Velja Radenkovic Mar 16 '15 at 14:31
  • If you don't want to be serialized then consider it moved outside the class. Or add custom deserialization logic to recreate it (and remove the readonly bit :(). This question could add more details to this: http://stackoverflow.com/questions/9328720/initialize-private-readonly-fields-after-deserializing – Juan Mar 16 '15 at 14:37