In a call like
F(ref a);   // ByRef parameter
the variable a is "used directly" by the body of method F. There's only one storage location. If the method F assigns to its parameter, that assignment will be visible to everyone who can see a, immediately. And conversely, if someone (outside F) assigns to a while method F is running, then the parameter of F will change to the new object "all of a sudden".
On the other hand, in a call like
F(a);  // normal value parameter
the variable a is first copied to a new variable, and then the new variable is used inside F. Now if the type of the parameter of F is a value type (like a struct or enum), the copy is done by value. So the entire data is copied. But if the type of the parameter is a reference type (class (including array type), interface, delegate), the copy of a involves a copy of the reference only.
To check your understanding of the value parameter case with a class type parameter, figure out what these methods do:
static void F1(List<int> list>)  // no ref modifier
{
    list.Clear();
}
static void F2(List<int> list>)  // no ref modifier
{
    list = new List<int>();
}
Here's some possibly interesting example with ref:
static void G(ref string a, ref string b)
{
    if (string.Equals(a, b))
        b += "_unique";
    // Is it now safe to say that a and b are distinct?
    // No. Anyone could have changed either a or b by now.
    // For example, a and b could "alias" public fields visisble to other threads.
}
As an example of the use of G above, consider the code var x = "initial"; G(ref x, ref x); in which case a will change together with b inside the method G.