I am looking at this myself now. I think I understand why there are differences in the results user graviton posted.
When you assign an IEnumerator to a variable, and pass that to the StartCoroutine, it is indeed a one-shot instance. However, re-assigning the IEnumerator to the same variable does reset it, as it creates a new instance, so that would be a solution to the original question. (There is an IEnumerator method ‘Reset’, which I thought might let it be re-used, but trying this results in a not-supported error message.)
When you assign as a string, I suspect Unity is doing some work under the hood to create a new instance each time it is called, effectively calling a new one-shot each time it is used. It also keeps track of all instances created with this string, and StopCoroutine method with a string shuts down all coroutines started with that string. It doesn’t seem possible to stop a coroutine started with an IEnumerable argument by using a StopCoroutine with a string argument, supporting this theory.
You can’t pause a string-started coroutine, because each time you call Start, it’s creating a new instance.
The last example graviton provides, where an anonymous IEnumerator is provided, you are unable to stop the coroutine because you don’t have a handle to the coroutine to do so; calling the same IEnumerable method in StopCoroutine will return a new instance of IEnumerable rather than locate the one already started.
In summary,
coroutine = MyCoroutine();
StartCoroutine(coroutine);
Starts or resumes a single coroutine instance, which will run to completion and then become ‘dead’, but can be paused with:
StopCoroutine(coroutine);
The variable ‘coroutine’ can be ‘reset’ by reassigning it to MyCoroutine().
====
StartCoroutine("MyCoroutine");
This will create a new coroutine instance each time it is called, and Unity will keep track of all of them, so they can all be stopped at once with:
StopCoroutine("MyCoroutine");
====
StartCoroutine(MyCoroutine());
This creates a new coroutine instance - but you will not be able to stop it with StopCoroutine. Because,
StopCoroutine(MyCoroutine());
This also creates a new coroutine instance, and so is not the same instance created with the above StartCoroutine. Doing this is effectively useless.