Showing posts with label pcl-tips-tricks. Show all posts
Showing posts with label pcl-tips-tricks. Show all posts

Monday, August 18, 2014

PCL Tips and Tricks: String sbyte* constructor

The introduction of Portable Class Libraries, PCL, considerably facilitates the sharing of functionality across managed Microsoft and Xamarin platforms. I am very enthusiastic about the PCL concept, and I have ported several .NET Framework open source projects to Portable Class Libraries. Along the way I have stumbled across various issues of making .NET Framework source code PCL compliant. In this mini-series I'll share my experiences and workarounds to facilitate the transfer to PCL for other developers.

Some of the PCL profiles do support unsafe code, in particular those profiles targeting Windows 8 and Windows Phone 8.1 (non-Silverlight). This means that it is possible to include for example pointers in the PCL code. On the other hand, methods dealing with unsafe code are rare in the .NET Portable Subset.

One case I ran into the other day is the String constructor. In .NET Framework, there are a few constructors taking an sbyte pointer as an argument, for example:

public String(sbyte* value, int startIndex, int length)

This constructor is not available in the .NET Portable Subset, so I had to come up with a replacement. And I came up with this portable method:

static unsafe String NewString(
    sbyte* value, int startIndex, int length)
{
  var chars = new char[length];
  for (var i = 0; i < length; ++i)
    chars[i] = (char)value[startIndex + i];
  return new String(chars);
}

So, instead of calling new String(...), the calls were changed to NewString(...).

I am still not entirely pleased with this approach of adding a new method to solve the issue. If any blog reader has a leaner solution to this issue, I am all ears.

Thursday, June 5, 2014

PCL Tips and Tricks: Extension methods to the rescue

The introduction of Portable Class Libraries, PCL, considerably facilitates the sharing of functionality across managed Microsoft and Xamarin platforms. I am very enthusiastic about the PCL concept, and I have ported several .NET Framework open source projects to Portable Class Libraries. Along the way I have stumbled across various issues of making .NET Framework source code PCL compliant. In this mini-series I'll share my experiences and workarounds to facilitate the transfer to PCL for other developers.

Now, here is a very common scenario when porting .NET class libraries to PCL:

public class SomeClassToPort
{
    public static byte[] SomeMethodToPort()
    {
        var stream = new MemoryStream();
        var writer = new StreamWriter(stream);
        writer.Write("Result: {0}, {1}", 10, "Hello");
        // some more writer operations ...

        writer.Close();   // Non-existent in PCL
        stream.Close();   // Non-existent in PCL

        return stream.ToArray();
    }
}

Correct, the Close() method is not available for streams, readers or writers in Portable Class Libraries! Since the method in practice only executes Dispose(), the Close() method has been excluded from PCL. Trying to build this code yields the following error:

error CS1061: 'System.IO.MemoryStream' does not contain a definition for 'Close' and no extension method 'Close' accepting a first argument of type 'System.IO.MemoryStream' could be found (are you missing a using directive or an assembly reference?)

Dispose() is generally available in PCL, so one solution is to replace all Close() calls with Dispose(). For those wanting to avoid the hassle and maintenance issues of replacing (potentially numerous) Close() calls, there is however a workaround.


Extension methods are a perfect fit for dealing with a scenario like the above. You can just add a static class with an arbitrary name to the PCL library, with code similar to this:

public static class CloseExtensions
{
    public static void Close(this Stream stream)
    {
        stream.Dispose();
    }

    public static void Close(this TextWriter writer)
    {
        writer.Dispose();
    }
}

Now, the compiler will "translate" stream.Close() into the call CloseExtensions.Close(stream) (analogously for the StreamWriter object) and the Portable Class Library can then build successfully. The extension methods perform practically the same operations as the Close() methods in the .NET Framework. Subsequent calls to Dispose() have no effect, so this implementation should be fail-safe. 

There is also no risk of name clashes; even when the PCL library is used in a .NET application the original Close() methods and the corresponding extension methods have completely different signatures (they can just be expressed equivalently in the code).

The Close() methods are probably the most obvious examples where this extension method technique can be applied, but whenever a PCL profile is not including an instance method of one type, the same technique may be applied. Other examples from the top of my head are:
  • several methods from the Type class which are not available for Windows 8 (f.k.a. Store or Metro apps); much of this functionality has been replaced by TypeInfo instance and extension methods,
  • Stream.BeginRead, Stream.EndRead, Stream.BeginWrite and Stream.EndWrite; again not available for Windows 8 but can be simulated using extension methods.

Friday, May 16, 2014

PCL Tips and Tricks: List.ForEach

The introduction of Portable Class Libraries, PCL, considerably facilitates the sharing of functionality across managed Microsoft and Xamarin platforms. I am very enthusiastic about the PCL concept, and I have ported several .NET Framework open source projects to Portable Class Libraries. Along the way I have stumbled across various issues of making .NET Framework source code PCL compliant. In this mini-series I'll share my experiences and workarounds to facilitate the transfer to PCL for other developers.

The List<T>.ForEach method is available on all managed Microsoft platforms, except one: Windows 8 (f.k.a. Windows Store or Metro). Possibly as a consequence of this, it is also not available in the Portable Class Libraries, not even when Windows 8 is not targeted.

The exact reasons for leaving out List<T>.ForEach from Windows 8 and PCL is unknown to me, but maybe the library maintainers want to discourage developers from using this method since it allows for side effects in a functional context (thanks Vagif Abilov for pointing this out). Fortunately, there is a simple replacement that should work practically always: use foreach instead!

So, instead of:

List<string> strs = ...;
strs.ForEach(str => DoSometing(str));

Use this:

List<string> strs = ...;
foreach (var str in strs) { DoSomething(str); }

I recently looked into the Clipper project, which is an open source library for clipping and offseting 2D polygons, available in several languages. I examined the C# source code, and it turned out that the author had used the List<T>.ForEach construct in his code. This was in fact the only issue preventing the C# Clipper code from being truly portable. Therefore, as a feature request I asked him to use foreach instead. This feature request was later implemented, and it is now possible to take the entire clipper.cs file and include it in any Portable Class Library.

Here are a few links about List<T>.ForEach vs. foreach:



Tuesday, May 13, 2014

PCL Tips and Tricks: Hashtable

The introduction of Portable Class Libraries, PCL, considerably facilitates the sharing of functionality across managed Microsoft and Xamarin platforms. I am very enthusiastic about the PCL concept, and I have ported several .NET Framework open source projects to Portable Class Libraries. Along the way I have stumbled across various issues of making .NET Framework source code PCL compliant. In this mini-series I'll share my experiences and workarounds to facilitate the transfer to PCL for other developers.

C# code that has its roots in pre-generic time (.NET Framework 1.x, that is) often tend to contain non-generic collections such as ArrayList and Hashtable.  In the Portable Class Libraries however, non-generic collections are avoided to the largest possible extent, and Hashtable is one of the missing classes.

Hashtable is simply a non-generic dictionary (it implements IDictionary) and it also shares the main methods and properties with the generic Dictionary<TKey, TValue> class, which is available across all PCL profiles.

It is thus actually quite straightforward to replace all Hashtable instances with Dictionary<TKey, TValue> instances. And as an added benefit, the dictionary can often be specialized as well, i.e. instead of replacing Hashtable with Dictionary<object, object> you can apply the actual key and value types.

Here is one example from the CSJ2K project, which is a C# class library for JPEG2000 encoding and decoding. In the .NET Framework-only project on Codeplex, in the ChannelDefinitionBox class, the field definitions is declared as a Hashtable where int is always used as keys and int[] as values.So, in my PCL adaptation of the CSJ2K project on Github, I have happily replaced Hashtable with Dictionary<int, int[]> in the adapted ChannelDefinitionBox class.

One additional comment is in place: in the aforementioned project CSJ2K, the hash tables are consistently created using the Synchronized method to ensure that the hash table is thread-safe. Dictionary<TKey, TValue> on the other hand does not guarantee thread-safety. A solution to this problem would be to instead use ConcurrentDictionary<TKey, TValue>, but this specialized dictionary is available in substantially fewer PCL profiles. If your PCL is targeting Windows Phone 8 or earlier, or Silverlight for that matter, ConcurrentDictionary will not be available. There is another workaround to this issue, but I'll save that for a subsequent post...

Friday, May 9, 2014

PCL Tips and tricks: ASCIIEncoding

The introduction of Portable Class Libraries, PCL, considerably facilitates the sharing of functionality across managed Microsoft and Xamarin platforms. I am very enthusiastic about the PCL concept, and I have ported several .NET Framework open source projects to Portable Class Libraries. Along the way I have stumbled across various issues of making .NET Framework source code PCL compliant. In this mini-series I'll share my experiences and workarounds to facilitate the transfer to PCL for other developers.

It appears to be very common that .NET Framework class libraries containing some kind of text processing relies on the ASCIIEncoding class, or alternatively the Encoding.ASCII static property.

ASCIIEncoding is not portable, but fortunately it can very easily replaced with another encoding that is available in (I think) all PCL profiles, namely UTF8Encoding. The UTF-8 encoding contains the ASCII character set as a sub-set, and it is even stated in the MSDN documentation for Encoding.ASCII that:

If your application requires 8-bit encoding (which is sometimes incorrectly referred to as "ASCII"), the UTF-8 encoding is recommended over the ASCII encoding. For the characters 0-7F, the results are identical, but use of UTF-8 avoids data loss by allowing representation of all Unicode characters that are representable. Note that the ASCII encoding has an 8th bit ambiguity that can allow malicious use, but the UTF-8 encoding removes ambiguity about the 8th bit.

So, whenever encountering ASCIIEncoding or Encoding.ASCII in source code that you are porting to PCL, simply replace it with UTF8Encoding and Encoding.UTF8, respectively.