As BitFlipper said, with out the method is required to set a value before it returns.

// This function won't compile because value isn't set on all code paths
void Foo(out int value)
{
}

// Whereas this is fine even though value isn't set.
void Bar(ref int value)
{
}

It also makes a difference on the calling side, however. Out parameters don't need to be initialized before passing them to a function:

void Test()
{
    int n;
    SomeFunc(ref n); // This won't compile; n is uninitialized.
    SomeOtherFunc(out n); // Whereas this is fine, even if n is uninitialized
    // n is guaranteed to have a value after the call to Foo, because
    // the function is required to assign it a value before returning.
}

Basically, use ref when you need to pass a value in and get a different value out, and use out when you only need to get a value out.

In general, try to avoid using ref/out parameters, because they lead to code that doesn't compose well. Sometimes it's unavoidable, but always try to find an alternative solution.

Just in case (since this is a common point of confusion): you do not need to use ref to be able to modify a parameter of a reference type (class) inside a function. With reference types you already passing a reference. Passing a reference type with ref means you pass a reference to a reference, which is only needed if you want to return a completely different instance to the caller.

class Foo
{
    public string Bar { get; set; }
}

void ModifyFoo(Foo value)
{
    value.Bar = "hello"; // The caller will see this change, even without ref
    value = new Foo(); // But the caller will *not* see this change; it doesn't get the new instance.
}

void ReplaceFoo(ref Foo value)
{
    value = new Foo(); // With ref, the caller will see this change and get the new instance.
    // I could've used out here, since we don't use the value that was passed in.
}