Evil Code #010 : Extension Methods

Back with Evil Code Series again. What would be the output of the following.

void Main()
{
PrintToString("SampleText");
PrintToDescription("SampleText");
PrintToString(null);
PrintToDescription(null);
}
public void PrintToString(string valueToPrint)
{
Console.WriteLine($"Printing From {nameof(PrintToString)} : {valueToPrint.ToString()}");
}

public void PrintToDescription(string valueToPrint)
{
Console.WriteLine($"Printing From {nameof(PrintToDescription)} : {valueToPrint.ToDescription()}");
}

public static class Extensions
{
public static string ToDescription(this string source)
{
return $"Description = {source??"Null"}";
}
}

The code attempts to prints 2 set of data, “SampleText” and Null Value. The PrintToString method, prints the output from the inbuild ToString() method, while the second method PrintToDescription, prints the output from an extension method.

The extension method, as such, doesn’t do anything fancy. It merely adds a prefix to the string (if not null or prints null).

It would be natural to expect the firs two method calls to print normally and then the last two calls, with null as paramter, to throw exceptions. But this is where things to change and expose the functioning of Extension methods.

While the extension methods work quite similiar to instance method, there is one fundamental difference. It has ability to execute even if the source instance if null.

In our given code, in the final call to PrintToDescription, even with a null paramter, the extension method is invoked, while the PrintToString would throw an exception as soon as null.ToString is encountered.

The output of the above code would be as following.

1. Printing From PrintToString : SampleText
2. Printing From PrintToDescription : Description = SampleText
3. // Throws Exception
4. Printing From PrintToDescription : Description = Null

Json Custom Filtering : Remove Properties of a Type T

One of the recent questions that came up in SO which fascinated me was how do one filter a Json string by removing properties from Json, which is of a particular Type. For example, consider the following Json.

{
'widget':
{
'debug': 'on',
'window': {
'title': 'Sample Widget',
'name': 'main_window',
'width': 500,
'height': 500
},
'image': {
'src': 'Images/Sun.png',
'name': 'sun1',
'hOffset': 250,
'vOffset': 250,
'alignment': 'center'
},
'text': {
'data': 'Click Here',
'size': 36,
'style': 'bold',
'name': 'text1',
'hOffset': 250,
'vOffset': 100,
'alignment': 'center',

}
}}

What if you want to remove all Json Properties that has a value of Integer Type. What would be a good way to achieve it if the format of Json is unknown ?

I ended up writing an extension method.

public static class Extensions
{
public static JToken RemoveFieldTypes(this JToken token,params JTokenType []fieldTypes)
{
JContainer container = token as JContainer;
if (container == null) return token;

var tokensToRemove = new List<JToken>();
foreach (JToken el in container.Children())
{
JProperty p = el as JProperty;
if(p!=null && fieldTypes.Contains(p.Value.Type))
{
tokensToRemove.Add(el);
}
el.RemoveFieldTypes(fieldTypes);
}
foreach (JToken el in tokensToRemove)
{
el.Remove();
}
return token;
}
}

Client Code Sample

JToken nodeList = JToken.Parse(strJson);
nodeList.RemoveFieldTypes(JTokenType.Integer);

Sample Ouput

{
"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window"
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"alignment": "center"
},
"text": {
"data": "Click Here",
"style": "bold",
"name": "text1",
"alignment": "center"
}
}
}

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.

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.