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);
}
}
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.
}
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:
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.
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.
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.
Re: Using keyword 'using' question.
Quote:
Originally Posted by
cilu
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.
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.
Quote:
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."
Re: Using keyword 'using' question.
Arjay, yes I know, but my question is 'why?'
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.
Re: Using keyword 'using' question.
Quote:
Originally Posted by
Arjay
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.
Re: Using keyword 'using' question.
I just tried it and dispose does not get called on the second object. So the warning is correct.
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'.