When shouldn’t you write ref this?

Last time, we saw that the this parameter to an instance method in a struct is passed by reference, allowing the method to re-assign this or pass it as a ref parameter.

Due to limitations in the CLR, the this parameter to an iterator method is not a reference to the caller’s struct, and is instead a copy of the value.  Quoting the spec (§7.6.7)

  • When this is used in a primary-expression within an instance method or instance accessor of a struct, it is classified as a variable. The type of the variable is the instance type (§10.3.1) of the struct within which the usage occurs.
    • If the method or accessor is not an iterator (§10.14), the this variable represents the struct for which the method or accessor was invoked, and behaves exactly the same as a ref parameter of the struct type.
    • If the method or accessor is an iterator, the this variable represents a copy of the struct for which the method or accessor was invoked, and behaves exactly the same as a value parameter of the struct type.

To explain why, you’ll need to understand how iterators are compiled.  As Jon Skeet explains, an iterator method is compiled into a nested class that implements IEnumerable, with the original code transformed into a state machine.  This nested class has fields to store the method’s parameters (which includes this for instance methods) so that the iterator code can use them. 

This is why iterators cannot take ref parameters; the CLR cannot store a reference (as opposed to a reference type) in a field.  Therefore, the this parameter is passed to iterator methods by value, not by reference.
This is also why anonymous methods in structs cannot use this; anonymous methods are also compiled to methods in separate classes and so cannot inherit the ref parameter.

This means that if you change the Mutate method from before into an iterator, the code will still compile (!), but the calling method will not see the changes.

static void Main() {
    Mutable m = new Mutable();
    m.MutateWrong().ToArray();    //Force the iterator to execute
    Console.WriteLine("In Main(): " + m.Value);

struct Mutable {
    public int Value;
    public IEnumerable<int> MutateWrong() {
        this = new Mutable();
        MutateStruct(ref this); 
        Console.WriteLine("Inside MutateWrong(): " + Value);
        yield break;
static void MutateStruct(ref Mutable m) { 
This code prints
Inside MutateWrong(): 1
In Main(): 0
In summary, don’t mutate structs in iterators (or at all, if you can help it).
I don’t know why this isn’t a compiler error.


Thanks for telling this story. Viki

You will find here essay writing tips that could be really useful for your future work. I think it could be really helpful

I am very enjoyed for this blog. Its an informative topic. It help me very much to solve some problems. Its opportunity are so fantastic and working style so speedy. I think it may be help all of you. Thanks a lot for enjoying this beauty blog with me. I am appreciating it very much! Looking forward to another great blog. Good luck to the author! all the best!
Jugar aqui friv juegos gratis!

With technology development and its penetration into the previously conservative and expensive educational process, we have faced the inevitable step: the flourishing era of online education https://bestwritingservice.com/online-test-assistance.html.

Since everything is evolving more on the internet and people want little to do. I want to recommend you Here https://papermasters.org/buy-argumentative-essay-on-any-topic-online you can cope with homework and writing your essay. He tried and convinced himself!

Post a Comment