Looping text with directional control
Your implementation can be greatly improved by using the System.Memory package. This will give you the new Memory&lt;char&gt; type (and if you're using .net-core it's already part of the SDK). With that you can create views of the string without creting any garbage.

At the same time you can make it more LINQ friendly. For this you can create the Slide extension that will return the slices of each part of the string and that accepts a Func for generating the offset for slicing. This one runs infinitely.

public static IEnumerable&lt;(Memory&lt;char&gt; X, Memory&lt;char&gt; Y)&gt; Slide(this string text, Func&lt;int, int&gt; calcOffset)
{
    var span = new Memory&lt;char&gt;(text.ToArray());
    while (true)
    {
        var offset = calcOffset(text.Length);
        var left = span.Slice(0, offset);
        var right = span.Slice(offset, text.Length - offset);
        yield return (right, left);
    }
}


You should also separate the logic for sliding and encapsulate each part in its own method. So you now have two of them.

public static Func&lt;int, int&gt; LeftToRight()
{
    var i = -1;
    return length =&gt;
    {
        i++;
        if (i &gt; length)
        {
            i = 0;
        }
        return i;
    };
}

public static Func&lt;int, int&gt; RightToLeft()
{
    var i = -1;
    return length =&gt;
    {
        i--;
        if (i &lt; 0)
        {
            i = length;
        }
        return i;
    };
}


To print it you can create another helper that encapsulates that part. Here you should replace the Thread.Sleep with Task.Delay which doesn't block/freeze the thread. With TimeSpan you can set the delay to whatever you want.

public static async Task PrintAsync(this IEnumerable&lt;(Memory&lt;char&gt; X, Memory&lt;char&gt; Y)&gt; source, TimeSpan delay)
{
    foreach (var element in source)
    {
        await Task.Delay(delay);
        Console.Clear();
        Console.Write(element.X);
        Console.WriteLine(element.Y);
    }
}




When you put everything together it'll look like that:

using  static Slider;

class Program
{
    static async Task Main(string[] args)
    {
        await
            "Hallo World"
                //.Slide(LeftToRight())
                .Slide(RightToLeft())
                .Take(20) // remove to run infinitely
                .PrintAsync(TimeSpan.FromMilliseconds(100));
    }
}


This is now garbage-free and does not create any additional sub-strings.