CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Sep 2009
    Posts
    62

    Using keyword 'using' question.

    Hi,

    I'm new to the concept of the keyword 'using' and am not sure if my code is correct.

    The compiler issues this warning: "Possibly incorrect assignment to local 'socket' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local."

    Does the warning mean that the dispose call is pointless because prior to the start of the using statement socket = null ??

    If this is wrong how should I have coded it?

    Many thanks.

    Code:
    Socket socket = null;
    
    using (socket)
    {
        IPHostEntry hostadd = Dns.GetHostEntry(server);
        IPEndPoint EPhost = new IPEndPoint(hostadd.AddressList[0], 123);
    
        socket = new Socket(EPhost.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
    
        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 8000);
    
        socket.SendTo(data, EPhost);
    
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
        EndPoint tempRemoteEP = (EndPoint)sender;
    
        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 15000);
    
        socket.ReceiveFrom(receiveData, ref tempRemoteEP);
    
        if (!IsResponseValid())
        {
            throw new Exception("Invalid response from server: " + server);
        }
    }

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Using keyword 'using' question.

    How about using using like this?

    Code:
     
    IPHostEntry hostadd = Dns.GetHostEntry(server);
    IPEndPoint EPhost = new IPEndPoint(hostadd.AddressList[0], 123);
    
    using ( Socket socket = new Socket( EPhost.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp ) )
    {
      // etc.
    }

  3. #3
    Join Date
    Oct 2002
    Location
    Timisoara, Romania
    Posts
    14,360

    Re: Using keyword 'using' question.

    Well, another proof that the compiler is smart.

    You first declare a null reference:
    Code:
    Socket socket = null;
    Then, you create this using block:
    Code:
    using (socket)
    {
    }
    That says: use this reference in the next block and when done, dispose it.

    But then you decide to change the reference:
    Code:
    socket = new Socket(EPhost.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
    And now the compiler its telling you that it will dispose the original reference, not the one created inside the block.
    Marius Bancila
    Home Page
    My CodeGuru articles

    I do not offer technical support via PM or e-mail. Please use vbBulletin codes.

  4. #4
    Join Date
    Sep 2009
    Posts
    62

    Re: Using keyword 'using' question.

    Thanks Arjay. Good idea. That removes the warning.

    Thanks also Cilu, for the explaination.

    I'll keep the code as Arjay suggested and keep in mind this 'problem' in future.

    Cheers.
    Last edited by mattst; November 19th, 2009 at 12:01 PM.

  5. #5
    Join Date
    Mar 2004
    Location
    Prague, Czech Republic, EU
    Posts
    1,701

    Re: Using keyword 'using' question.

    As well you can write it this way
    Code:
    Socket socket = new Socket( EPhost.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
    using (socket)
    {
      // etc.
    }
    but this is just for couriosity, the Arjay's version is more common and I preferre it wherever it is possible.
    • Make it run.
    • Make it right.
    • Make it fast.

    Don't hesitate to rate my post.

  6. #6
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: Using keyword 'using' question.

    Quote Originally Posted by cilu View Post
    And now the compiler its telling you that it will dispose the original reference, not the one created inside the block.
    Not disagreeing with you, the compiler is clearly saying that, but I'm surprised.

    I thought 'using' was basically:

    Code:
    Socket socket = new Socket(/* ... */);
    
    try
    {
        // ...
    }
    finally
    {
    socket.Dispose();
    }
    So if I were to change what socket refers to (a very bad idea!) then the new object would be disposed.
    My hobby projects:
    www.rclsoftware.org.uk

  7. #7
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Using keyword 'using' question.

    Right but it's more like

    Code:
    Socket socket = null;
     
    try
    {
      socket = new Socket(/* ... */);
      // ...
    }
    finally
    {
      socket.Dispose();  // socket is null here because using acts on the original socket variable value.
    }
    The compiler indicates as much.

    The compiler issues this warning: "Possibly incorrect assignment to local 'socket' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local."

  8. #8
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: Using keyword 'using' question.

    Arjay, yes I know, but my question is 'why?'
    My hobby projects:
    www.rclsoftware.org.uk

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Using keyword 'using' question.

    It's a warning, so at the time the using block was expanded into a try/finally block, the socket object was null. The compiler issued the warning because it doesn't know until later that the object has been new'd up.

    I would expect that after the new statement, the non-null socket object will be disposed.

  10. #10
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: Using keyword 'using' question.

    Quote Originally Posted by Arjay View Post
    I would expect that after the new statement, the non-null socket object will be disposed.
    That's the opposite of the warning though. The compiler knows the value has changed. It says: "The Dispose call or unlocking will happen on the original value of the local."

    I'll build an example and will have a look at the MSIL code.
    My hobby projects:
    www.rclsoftware.org.uk

  11. #11
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Using keyword 'using' question.

    I just tried it and dispose does not get called on the second object. So the warning is correct.

  12. #12
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: Using keyword 'using' question.

    Looking at the compiled MSIL code, it seems that ...

    Code:
    Stream stream = new FileStream(@"C:\temp\file.txt", FileMode.Open);
    
    using (stream)
    {
        stream = new FileStream(@"C:\temp\file.txt", FileMode.Open);
    }
    ... is turned into ...

    Code:
    Stream stream = new FileStream(@"C:\temp\file.txt", FileMode.Open);
    
    using (Stream temp = stream)
    {
        stream = new FileStream(@"C:\temp\file.txt", FileMode.Open);
    }
    ... by the compiler:

    Code:
      IL_0000:  ldstr      "C:\\temp\\file.txt"
      IL_0005:  ldc.i4.3
      IL_0006:  newobj     instance void [mscorlib]System.IO.FileStream::.ctor(string,
                                        valuetype [mscorlib]System.IO.FileMode)
      IL_000b:  stloc.0
      IL_000c:  ldloc.0
      IL_000d:  stloc.1
      .try
      {
        IL_000e:  ldstr      "C:\\temp\\file.txt"
        IL_0013:  ldc.i4.3
        IL_0014:  newobj     instance void [mscorlib]System.IO.FileStream::.ctor(string,
                                          valuetype [mscorlib]System.IO.FileMode)
        IL_0019:  stloc.0
        IL_001a:  leave.s    IL_0026
      }  // end .try
      finally
      {
        IL_001c:  ldloc.1
        IL_001d:  brfalse.s  IL_0025
        IL_001f:  ldloc.1
        IL_0020:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
        IL_0025:  endfinally
      }  // end handler
      IL_0026:  ret
    Note:
    ldloc.0 means 'load from local variable zero', i.e. 'stream'.
    stloc.1 means 'store in local variable one', i.e. 'temp'.
    Last edited by Zaccheus; November 23rd, 2009 at 04:34 AM.
    My hobby projects:
    www.rclsoftware.org.uk

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured