Run length encoding in C# This is the original question:
https://www.geeksforgeeks.org/run-length-encoding/


  Given an input string, write a function that returns the Run Length
  Encoded string for the input string. For example, if the input string
  is “wwwwaaadexxxxxx”, then the function should return “w4a3d1e1x6”.


the only change I did is that if the character appears once there is no need to print 1 after the letter.

Please review for perfomance

using System;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace StringQuestions
{
    /// &lt;summary&gt;
    /// https://www.geeksforgeeks.org/run-length-encoding/
    /// &lt;/summary&gt;
    [TestClass]
    public class RunLengthEncoding
    {
        [TestMethod]
        public void RunLengthEncodingTest()
        {
            string str = "wwwwaaadexxxxxxywww";
            string expected = "w4a3dex6yw3";
            Assert.AreEqual(expected, RLE.Encode(str));
        }
    }

    public class RLE
    {
        public static string Encode(string str)
        {
            str = str.ToLower();
            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0; i &lt; str.Length; i++)
            {
                int counter = 1;
                if (!char.IsLetter(str[i]))
                {
                    throw new ArgumentException("string should contains only letters");
                }

                while (i &lt; str.Length - 1 &amp;&amp; str[i] == str[i + 1])
                {
                    counter++;
                    i++;
                }

                if (counter == 1)
                {
                    stringBuilder.Append(str[i]);
                }
                else
                {
                    stringBuilder.Append(str[i]);
                    stringBuilder.Append(counter);
                }
            }

            return stringBuilder.ToString();
        }
    }
}
One thing I noticed.  You're modifying the loop counter inside the loop to run another loop.  This is one way in a large project to create unseen bugs. By keeping track of the previous character it is fairly easy to code this with only one loop.

Your trapping strings that have other characters besides letters, but you're neglecting empty strings and null.

Here's one way the revised code can look:

static string Encode(string input)
{
    if (input == null || input.Length == 0)
    {
        ArgErrHandler("String must have at least one letter.");
    }
    if (input.Any(x =&gt; !char.IsLetter(x)))
    {
        ArgErrHandler("String must have only letters.");
    }
    if (input.Length == 2 || input.Length == 1)
    {
        return (input.Length == 1 || input[0] != input[1]) ? input : $"{input[0]}{2}";
    }
    int limit = input.Length - 1;
    int counter = 1;
    StringBuilder sb = new StringBuilder();
    int i = 1;
    char prev = '\0';
    do
    {

        prev = input[i - 1];
        if (input[i] == prev)
        {
            ++counter;
        }
        else
        {
            if (counter &gt; 1)
            {
                sb.Append($"{prev}{counter}");
            }
            else
            {
                sb.Append(prev);
            }
            prev = input[i];
            counter = 1;
        }
    } while (++i &lt; limit);
    if (input[i] == prev)
    {
        ++counter;
        sb.Append($"{prev}{counter}");
    }
    else
    {
        if (counter &gt; 1)
        {
            sb.Append($"{prev}{counter}{input[i]}");
        }
        else
        {
            sb.Append($"{prev}{input[i]}");
        }
    }
    return $"{sb}";
}
private static void ArgErrHandler(string message)
{
    throw new ArgumentException(message);
}