Q:

Foreach loop passing the iteration variable to a method with and without ref - dont get why it wont allow it with ref

This morning I've struggled to understand the following and I am hoping someone has a good explanation of why this wont work.  I made an example on LinqPad that replicates my issue:
void Main()
{
  var myPeople = new People();
  myPeople. MyPeople. Add(new Person { Name = "Joe", Surname = "Doe" });

  foreach (var person in myPeople. MyPeople)
  {
      //this is intermediate variable is still a reference to the iteration variable
       var intermediate = person;
       myPeople. ChangeName(ref intermediate);

      //both names were changed, so why cant i just pass in 'person' directly since its still changing it. 

      intermediate. Name. Dump();
      person. Name. Dump();
  }

}

 public class People
 {
     public People()
     {
        MyPeople = new List<Person>();
     }

    public List<Person> MyPeople { get; set; }

    public void ChangeName(ref Person person)
    {
       person. Name = "Changed";
    }
}

public class Person
{
   public string Name { get; set; }

   public string Surname { get; set; }
}

So this post explains the foreach variable is a read only variable that is why you can't replace it with another- makes sense, but if i pass it into the method above ChangeName with a ref, compiler wont allow it CS1657.  But if i remove the ref on the ChangeName method it will allow me to pass in the foreach variable, but technically its still a reference without explicitly saying its a ref right?  
So why is this happening?  Furthermore if I assign it to an intermediate variable above, then it will allow me to pass it in as a ref even though its still a reference to the original, so technically pointing to the same memory location, meaning same object right?  
So my question really is why the C# compiler wont let me pass in iteration variable to a method with a ref
Further clarity on question by Rafalon: 
Why does the compiler not allow myPeople. ChangeName(ref person) but allows myPeople. ChangeName(ref intermediate) when the person variable points to the same object as the intermediate variable? 

A:

Ultimately, the notes on CS1657 explains all of this; the l-value of a regular foreach is considered "readonly" - you can't do:
person = new Person();

for example.  The ref usage requires the parameter not be read-only, otherwise we have violated the promise of read-only-less, because the method could modify something that is meant to be read-only.  In this case, since Person is a class, this only relates to the actual reference itself, not the underlying object. 
There is good news, though: we now have in, which is like ref, but for read-only scenarios, so: change public void ChangeName(ref Person person) to public void ChangeName(in Person person) and it should work:
myPeople. ChangeName(in person);

The restriction on this is that you then, in your ChangeName method, can't do things like:
public void ChangeName(in Person person)
{
    person = new Person(); // invalid
}

Emphasis: this in usage isn't really intended for classes; it is intended for struct, and in particular readonly struct - to avoid defensive stack copies of complex and large value-types. 
In latest versions of C#, there is also a ref readonly concept, by-which the l-value is a ref Foo (for whatever type Foo).  This requires a custom iterator with a public ref Foo Current {get;} accessor instead of a public Foo Current {get;} accessor, i.e. it is explicitly tied into ref-return.  When the l-value is a ref, you can use it in a method that takes a ref. 

Important emphasis, although I realize OP knows this: you don't need ref in this scenario since Person is a class itself; the code would work just fine without the ref, and the object would be updated correctly.