The difference between returning an actual collection and using yield is just the type of the object that you return.
If you return any collection that implements IEnumerable<T>, the actual type of the object returned will be that type. If you for example return a List<T>, the reference returned will be of the type IEnumerable<T> but the actual type of the object that the reference points to is an instance of List<T>.
If you use yield, the compiler will create an enumerator object without a known name. The type of the reference returned will also be IEnumerable<T>, but the actual type of the object that the reference points to will be something that the compiler creates.
For example getting the name of the type of an enumerator created for an integer:
Console.WriteLine(Cat<int>(42).GetType().Name);
will show the internal name that the compiler uses, for example this result that I got from the code:
<Cat>d__5`1
If the function would return a List<int> instead, the type would display as:
List`1
The motivation for letting the compiler create an enumerator for this is probably just that it is shorter than something like this:
static IEnumerable<T> Cat<T>(T t) {
List<T> list = new List<T>(1);
list.Add(t);
return list;
}
(You can write it a bit shorter using shortcuts in newer versions of C#, but still not as short as a yield.)
When the type is a collection, you can cast the reference to the actual type and change the value in the collection:
IEnumerable<int> ienum = Cat<int>(42);
((List<int>)ienum)[0] = 1337;
foreach (int value in ienum) {
Console.WriteLine(value);
}
will output:
1337