I wonder why does it not compile?
public static void Main(string[] args)
{
using (MyStruct sss = new MyStruct())
{
sss.s = "fsdfd";// Cannot modify members of 'sss' because it is a 'using variable'
//sss.Set(12); //but it's ok
}
}
public struct MyStruct : IDisposable
{
public int n;
public string s;
public void Set(int n)
{
this.n = n;
}
public void Dispose()
{
Console.WriteLine("dispose");
}
}
UPDATE: But it works perfect. Why?
public static void Main(string[] args)
{
using (MyClass sss = new MyClass())
{
sss.Field = "fsdfd";
}
}
public class MyClass:IDisposable {
public string Property1 { get; set; }
public string Field;
public void Method1 (){}
public void Dispose()
{
Console.WriteLine("dispose class");
}
}
IDisposable Interface (System) Provides a mechanism for releasing unmanaged resources.
IDisposable is an interface defined in the System namespace. It is used to release managed and unmanaged resources. Implementing IDisposable interface compels us to implement 2 methods and 1 boolean variable – Public Dispose() : This method will be called by the consumer of the object when resources are to be released.
By default, the garbage collector automatically calls an object's finalizer before reclaiming its memory. However, if the Dispose method has been called, it is typically unnecessary for the garbage collector to call the disposed object's finalizer.
What is a ref struct? Well, a ref struct is basically a struct that can only live on the stack. Now a common misconception is that since classes are reference types, those live on the heap and structs are value types and those live on the stack.
The class and struct scenarios are actually the same but you see different effects.
When you change the class example to :
using (MyClass sss = new MyClass())
{
sss = null; // the same error
sss.Field = "fsdfd"; // ok
}
You will get the same error on the first assignment.
The explanation is: You cannot change (mutate) the using-variable. But for a class that applies to the reference, not to the instance.
And the lesson is: Don't use structs. And especially don't use mutable structs.
A number of people have linked to my article about mutating value types and why it is a bad idea. Though it is important to understand those concepts when understanding why its a bad idea to dispose a struct, and a worse idea to mutate the struct when you do, that is not actually the right article to link to. The one you want to read that explains all this in excruciating detail is:
http://ericlippert.com/2011/03/14/to-box-or-not-to-box/
In short: "using" makes a copy of the value type, and you are therefore disposing a copy. That means you have to be very careful -- if the value is, say, an OS handle, there might be lots of copies of that value lying around memory, and you'll need to make sure that you dispose it exactly once no matter how many copies there are.
See also If my struct implements IDisposable will it be boxed when used in a using statement?
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