I have need of a .net structure (it mimics a connected devices internal map) and I want to use a try catch block since I'm using Marshall.PtrToStructure() and associated GChandle stuff. However I when I put the structures field assignments inside the try catch block I get this error "field1 must be fully assigned before control is returned to sender". The basic code works fine without the try catch block. Is there any way around this error while using try catch blocks? Should I use try catch?
[StructLayout( LayoutKind.Sequential )]
public struct Effects
{
public UInt16 field_1;
public UInt16 field_2;
...
public Effects(byte[] effectsData)
{
GCHandle gch;
try
{
gch = GCHandle.Alloc( effectsData, GCHandleType.Pinned );
IntPtr pEffects = gch.AddrOfPinnedObject( );
this = (Effects)Marshal.PtrToStructure( pEffects, typeof(Effects ) );
}
catch (Exception ex)
{
}
finally
{
if (gch.IsAllocated)
gch.Free( );
}
}
}
The constructor must guarantee that if it returns normally then all the fields are filled in.
Suppose your code throws an exception on the first line of the try
. Then you catch the exception, eat it, and return, without having ever filled in any of the fields! The compiler detects this and disallows the program.
Eating every exception is almost certainly the wrong thing to do here. Do you really want to return an uninitialized structure if there was an unhandled and unexpected arbitrary exception?
If that is what you want to do then you can simply say:
public Effects(byte[] effectsData) : this() {
that will guarantee that the fields are initialized to their default values before the ctor block runs.
But again: is that really what you want to do? This code looks incredibly dangerous to me.
What do you want to happen in case of an exception? As your code stands now, if an exception occurs in the try block, the exception is swallowed (since your catch block is empty), and the structure is uninitialized -- this is exactly what the compiler is complaining about.
If you need the try-catch block only for the finally part, don't use the catch block at all but just try-finally. Let errors bubble up to the user interface by not catching them. No catch block is (almost) always better than an empty catch block. Empty catch blocks make debugging a nightmare, since your code just "doesn't work" with no indication to what went wrong.
Thus, I'd rewrite your code as follows:
public Effects(byte[] effectsData)
{
GCHandle gch = GCHandle.Alloc( effectsData, GCHandleType.Pinned );
try
{
IntPtr pEffects = gch.AddrOfPinnedObject( );
this = (Effects)Marshal.PtrToStructure( pEffects, typeof(Effects ) );
}
finally
{
if (gch.IsAllocated)
gch.Free( );
}
}
(If an error occurs in GCHandle.Alloc
, gch will not be assigned, so there's no need to include it in the try-finally block.)
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