Updated Span API : NonPortableCast and AsReadOnlySpan to MemoryMarshal.Cast and AsSpan

One of the interesting changes (not sure why Microsoft changed this) was moving/changing the Span<T> API’s a bit. For example, the Span<T>.NonPortableCast Method was moved as an extension method under MemoryMarshal.

Previous API

Span<byte> byteSpan = BitConverter.GetBytes(originalPrimitiveType);
Span<int> intSpan = byteSpan.NonPortableCast<byte, int>();

Current API

Span<byte> byteSpan = BitConverter.GetBytes(originalPrimitiveType);
Span<int> intSpan = MemoryMarshal.Cast<byte, int>(byteSpan);

Similarly, the string.AsReadonlySpan method has been renamed. The new API is as follows.

Previous API

ReadOnlySpan<char> keyString = "SomeText".AsReadOnlySpan();

Current API

ReadOnlySpan<char> keyString = "SomeText".AsSpan();

The MemoryMarshal extensions can be found under the System.Runtime.InteropServices namespace. Code discussed in my earlier post about Benchmarking Span has been updated in my Github.

Advertisements

Deconstruct and Extension Methods

In an earlier post, we explored the Deconstruct feature for Non-Tuples. It was a pretty useful feature that came along in the 7.x series . If one does have access to source, adding deconstruct is quite easy. But what about classes we do not have (source code) access to ? For example, the .Net framework classes ? Can we add a deconstruct to it ? It turns out, it is quite simple as well. Extension Methods allows us to add deconstruct to existing classes without breaking the Open Closed Principle.

For demonstration purpose, let us write a deconstruct for Point Class under the System.Drawing namespace.

public static class ExtensionMethods
{
    public static void Deconstruct(this Point source,out double x,out double y)
    {
        x = source.X;
        y = source.Y;
    }
}

void Main()
{
       Point point = new Point(100,500);
       var (x,y) = point;
       Console.WriteLine($"Point.X={x},Point.Y={y}");
}

As observed, it is quite easy to add deconstruct to your existing classes using the Extension Methods.

Linq Recipes : IsIncreasing/IsDecreasing & IsAlternating

LINQ, ever since its introduction has turned out to be one of the favorite tools for .Net Developers. The post focus on couple of quick recipes for common scenarios.

Scenario 001
You have a collection of objects and you would like verify if the collection is sorted in increasing/decreasing order.

Recipe

We could always sort the collection and compare with the original version, however, if you really want to stick to a LINQ based solution, following extension methods is one approach.

public static bool IsIncreasing<TSource>(this IEnumerable<TSource> data) 
{ 
   return data.Zip(data.Skip(1),(first, second) => Comparer.Default.Compare(first,second) < 0).All(b => b);
}


public static bool IsDecreasing<TSource>(this IEnumerable<TSource> data)
{
   return data.Zip(data.Skip(1),(first, second) => Comparer.Default.Compare(first,second) > 0).All(b => b);
}

Demo

void Main()
{
       var itemSet1 = new[] {1,3,4,5,6};
       var itemSet2 = new[] {5,4,3,2,1};
       Console.WriteLine($"Is {nameof(itemSet1)} increasing ? {itemSet1.IsIncreasing()}" );
       Console.WriteLine($"Is {nameof(itemSet1)} decreasing ? {itemSet1.IsDecreasing()}" );
       Console.WriteLine($"Is {nameof(itemSet2)} increasing ? {itemSet1.IsIncreasing()}" );
       Console.WriteLine($"Is {nameof(itemSet2)} decreasing ? {itemSet1.IsDecreasing()}" );
}

Output

Is itemSet1 increasing ? True
Is itemSet1 decreasing ? False
Is itemSet2 increasing ? True
Is itemSet2 decreasing ? False

Scenario 002:

Consider you have a Collection ‘A’. You want to ensure that each element in the series vary in an alternating way, that is, for each element in A, A[i] < A[i+1] > A[i+2] or A[i] > A[i+1] < A[+2]. For example, for the collection {1,3,2,4,3,5} follows the pattern.

Recipe
Once again we will write the solution as an extension method. Well, that’s easier to ‘reuse’ right.

public static bool IsAlternating<TSource>(this IEnumerable<TSource> dataList)
{
       return VerifyIfAlternating(dataList.ToList(),true) || VerifyIfAlternating(dataList.ToList(),false);
}

private static bool VerifyIfAlternating<TSource>(IList<TSource> data,bool toggle)
{
return data.Zip(data.Skip(1), (first, second) =>
                                            {
                                                toggle = !toggle;
                                                return Comparer.Default.Compare(first,second) > 0 == toggle;
                                            })
                                            .All(b=>b);
                                                              
}

Demo

void Main()
{
       var itemSet3 = new[] {1,4,1,4,1};
       var itemSet4 = new[] {2,4,3,2,1};

       Console.WriteLine($"Is {nameof(itemSet3)} alternating ? {itemSet3.IsAlternating()}" );
       Console.WriteLine($"Is {nameof(itemSet4)} alternating ? {itemSet4.IsAlternating()}" );

}

Output

Is itemSet3 alternating ? True
Is itemSet4 alternating ? False

That’s it for now. This is one series I would like to continue.

WaitForFirstN Tasks Method

There is a definite gap between TAP Utilities Task.WaitAny and Task.WaitAll. How do we wait for the first ‘N’ tasks from an array of tasks. That is one utility that is missing from TAP’s rich repository. It might not be hard to implement one by yourself though.

public static int[] WaitForFirstN(this System.Threading.Tasks.Task[] tasks,int numberOfTasks)
{
   if (numberOfTasks > tasks.Length) throw new ArgumentOutOfRangeException();

   var _taskDictionary = Enumerable.Range(0, tasks.Length).ToDictionary(x => tasks[x]);
   List<int> completedTaskIndices = new List<int>();

   while (completedTaskIndices.Count < numberOfTasks) 
   { 
      var index = System.Threading.Tasks.Task.WaitAny(tasks);
      completedTaskIndices.Add(_taskDictionary[tasks[index]]); 
      tasks = tasks.Where(x => x.Id != tasks[index].Id).ToArray();
    }
    return completedTaskIndices.ToArray();
}

The above code uses existing Task Collaborators Task.WaitAny to wait for ‘N’ tasks specified by numberOfTasks parameter. Let’s try the following in code.

 
System.Threading.Tasks.Task[] tasks = new System.Threading.Tasks.Task[5];

[TestInitialize]
public void Init()
{
  for (int ctr = 0; ctr <= 4; ctr++)
  {
    int factor = ctr;
    tasks[ctr] = System.Threading.Tasks.Task.Run(() => Thread.Sleep(factor * 250 + 50));
   }
}
[TestMethod]
public void WaitForFirstN_ValidResult_EqualsExpected()
{
   var completedTaskList = tasks.WaitForFirstN(3);
   CollectionAssert.AreEqual(new int[] { 0, 1, 2 }, completedTaskList);
}

Code shown in this sample can also be on my GitHub.

One interesting though. Curious why Framework doesn’t allow us to create Static Extension Methods for types.