Q:

Check if a string is sorted

I have a string, simplified "12345" which is sorted. The string couild contain Digits (0-9) or letters (a-z). In case of a mixed use the natural sort order. I need a method to verify if this is true. 
Attempt with linq technique:
string items1 = "2349"; //sorted
string items2 = "2476"; //not sorted, 6<>7

bool sorted1 = Enumerable.SequenceEqual(items1.OrderBy(x => x), items1); //true
bool sorted2 = Enumerable.SequenceEqual(items2.OrderBy(x => x), items2); //false

but there could be also a descending sort order.
Is there a better way then
string items3 = "4321";
bool sorted3 = Enumerable.SequenceEqual(items3.OrderBy(x => x), items3) || Enumerable.SequenceEqual(items3.OrderByDescending(x => x), items3);

to check if a string is sorted? Maybe some built in solution?

A:

Your solution in fine and very readable. One problem with it is that it requires ordering the string which is O(n * log(n)), this can be solved by iterating the string without sorting it.
For example:
var firstDifs = items1.Zip(items1.Skip(1), (x, y) => y - x);

This Linq projects every 2 items in the first string to a number which indicates their difference, So if you have items1 = "1245" the output will be:

firstDifs: {1, 2, 1}

Now all you need to do is to validate that firstDifs is either ascending or descending:
bool firstSorted = firstDifs.All(x => x > 0) || firstDifs.All(x => x < 0); //true

Now:

Skip is O(1) since the amount of actions required to skip 1 cell is 
constant.
Zip is O(n).
All is O(n).

So the whole solution is O(n).
Note that it will be more efficient with a simple loop, also if the first All has returned false because the 3487th item changes its direction (for example: 1234567891), the second All will run for no reason with the Zip running twice as well (Until where All require) - since there are two iterations of All and Linq evaluates them lazily.

A:

It requires a reducer. In C#, it's Enumerable.Aggregate. It's O(n) algorithm.
var query = "123abc".Aggregate(new { asceding = true, descending = true, prev = (char?)null }, 
(result, currentChar) =>
    new 
    { 
       asceding = result.prev == null || result.asceding && currentChar >= result.prev, 
       descending = result.prev == null || result.descending && currentChar <= result.prev, 
       prev = (char?)currentChar 
    }
);
Console.WriteLine(query.asceding || query.descending );

A:

I once had to check something similar to your case but with huge data streams, so performance was important. I came up with this small extension class which performs very well:
public static bool IsOrdered<T>(this IEnumerable<T> enumerable) where T: IComparable<T>
{
    using (var enumerator = enumerable.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            return true; //empty enumeration is ordered

        var left = enumerator.Current;
        int previousUnequalComparison = 0;

        while (enumerator.MoveNext())
        {
            var right = enumerator.Current;
            var currentComparison = left.CompareTo(right);

            if (currentComparison != 0)
            {
                if (previousUnequalComparison != 0
                    && currentComparison != previousUnequalComparison)
                    return false;

                previousUnequalComparison = currentComparison;
                left = right;
            }
        }
    }

    return true;
}

Using it is obviously very simple:
var items1 = "2349";
var items2 = "2476"; //not sorted, 6<>7
items1.IsOrdered(); //true
items2.IsOrdered(); //false

