Two-way implicit casting

I’m presently writing a framework that wraps a C API using interop. Many of the classes/structs defined in the C library already exist in .NET, but I have to re-implement them anyway so that I can interface with the library. People accustomed to the .NET classes won’t be fond of this because they already have a set of classes that work well, and the new ones won’t work with existing .NET methods. There is a simple solution to this, however! Implicit casting!

Here’s a sample of how I made my Color struct compatible with the one defined in System.Drawing.Color:

[StructLayout(LayoutKind.Sequential)]
public struct Color
{
    public byte R, G, B, A;

    public static implicit operator System.Drawing.Color(Color c)
    {
        return System.Drawing.Color.FromArgb(c.A, c.R, c.G, c.B);
    }

    public static implicit operator Color(System.Drawing.Color c)
    {
        return new Color {R = c.R, G = c.G, B = c.B, A = c.A};
    }
}

Note that System.Drawing.Color uses ints instead of bytes for its colors, and they aren’t necessarily stored in the same memory location, so I couldn’t use that class directly. You can, however, convert back and forth between the two classes without any loss of data, so this is a perfect case for implicit casting. If the two classes aren’t convertible without some data changing, you should use explicit casting instead, or perhaps a static factory method.

I was curious, however, to know what would happen if an implicit casting method was defined in both classes. Here’s an example:

class A
{
    public static implicit operator B(A a)
    {
        Console.WriteLine("A::B");
        return new B();
    }
}

class B
{
    public static implicit operator B(A a)
    {
        Console.WriteLine("B::B");
        return new B();
    }
}

class Program
{
    public static void F(B b)
    {
        Console.WriteLine("F()");
    }

    static void Main(string[] args)
    {
        var a = new A();
        F(a);
        Console.ReadLine();
    }
}

How does it know which method to call? The answer: it doesn’t! This actually gives the following error:

Ambiguous user defined conversions ‘ImplicitTest.A.implicit operator ImplicitTest.B(ImplicitTest.A)’ and ‘ImplicitTest.B.implicit operator ImplicitTest.B(ImplicitTest.A)’ when converting from ‘ImplicitTest.A’ to ‘ImplicitTest.B’

There is a way you can still utilize one of conversion methods, but it isn’t pretty. Here’s the solution work-around:

static void Main(string[] args)
{
    var method = typeof (A).GetMethod("op_Implicit", new[] {typeof (A)});
    var converter = (Func<A, B>) Delegate.CreateDelegate(typeof (Func<A, B>), method);
    var a = new A();
    F(converter.Invoke(a));
    Console.ReadLine();
}

[credit]

The real solution would be to just delete one of the methods, if you can!

Posted in

High quality image resize (C#)

You can use this class to resize images proportionally (maintaining aspect ratio), or to resize an image to an exact size and crop off excess (useful for making nice thumbnails):

 


public static class ImageExt {
  public static Image Resize(this Image img, int srcX, int srcY, int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
    var bmp = new Bitmap(dstWidth, dstHeight);
    using(var graphics = Graphics.FromImage(bmp)) {
      graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
      graphics.CompositingMode = CompositingMode.SourceCopy;
      graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
      using(var wrapMode = new ImageAttributes()) {
        wrapMode.SetWrapMode(WrapMode.TileFlipXY);
        var destRect = new Rectangle(0, 0, dstWidth, dstHeight);
        graphics.DrawImage(img, destRect, srcX, srcY, srcWidth, srcHeight, GraphicsUnit.Pixel, wrapMode);
      }
    }
    return bmp;
  }

  public static Image ResizeProportional(this Image img, int width, int height, bool enlarge = false) {
    double ratio = Math.Max(img.Width / (double) width, img.Height / (double) height);
    if (ratio &lt; 1 &amp;&amp; !enlarge) return img;
    return img.Resize(0, 0, img.Width, img.Height, M2.Round(img.Width / ratio), M2.Round(img.Height / ratio));
  }
  public static Image ResizeCropExcess(this Image img, int dstWidth, int dstHeight) {
    double srcRatio = img.Width / (double) img.Height;
    double dstRatio = dstWidth / (double) dstHeight;
    int srcX,
    srcY,
    cropWidth,
    cropHeight;
    if (srcRatio &lt; dstRatio) // trim top and bottom
    {
      cropHeight = dstHeight * img.Width / dstWidth;
      srcY = (img.Height - cropHeight) / 2;
      cropWidth = img.Width;
      srcX = 0;
    } else // trim left and right
    {
      cropWidth = dstWidth * img.Height / dstHeight;
      srcX = (img.Width - cropWidth) / 2;
      cropHeight = img.Height;
      srcY = 0;
    }
    return Resize(img, srcX, srcY, cropWidth, cropHeight, dstWidth, dstHeight);
  }
}
Posted in

Convert decimal numbers to any base (C#)

You can use this little function to convert a decimal to any base. I use it for compacting large numbers.

public static class BaseConverter
{
    public static string Encode(BigInteger value, int @base=0, string chars="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    {
        if (@base <= 0) @base = chars.Length;
        var sb = new StringBuilder();
        do
        {
            int m = (int)(value % @base);
            sb.Insert(0, chars[m]);
            value = (value - m) / @base;
        } while (value > 0);
        return sb.ToString();
    }
}

Or you can use it to make a nice GUID:

private static BigInteger UnsignedBigInt(byte[] bytes)
{
    if ((bytes[bytes.Length - 1] & 0x80) != 0) Array.Resize(ref bytes, bytes.Length + 1);
    return new BigInteger(bytes);
}

private static string GetUniqueFileName(string extension)
{
    return BaseConverter.Encode(UnsignedBigInt(Guid.NewGuid().ToByteArray()), 0, "0123456789abcdefghijklmnopqrstuvwxyz_-") + extension;
}
Posted in

JSON Prettifier

This is a simple class I wrote to nicely format a JSON string. Just call it with JsonFormatter.PrettyPrint(yourJsonString)

public static class JsonFormatter
{
    public static string Indent = "    ";

    public static void AppendIndent(StringBuilder sb, int count)
    {
        for (; count > 0; --count) sb.Append(Indent);
    }

    public static bool IsEscaped(StringBuilder sb, int index)
    {
        bool escaped = false;
        while (index > 0 && sb[--index] == '\\') escaped = !escaped;
        return escaped;
    }

    public static string PrettyPrint(string input)
    {
        var output = new StringBuilder(input.Length * 2);
        char? quote = null;
        int depth = 0;

        for(int i=0; i<input.Length; ++i)
        {
            char ch = input[i];

            switch (ch)
            {
                case '{':
                case '[':
                    output.Append(ch);
                    if (!quote.HasValue)
                    {
                        output.AppendLine();
                        AppendIndent(output, ++depth);
                    }
                    break;
                case '}':
                case ']':
                    if (quote.HasValue)  
                        output.Append(ch);
                    else
                    {
                        output.AppendLine();
                        AppendIndent(output, --depth);
                        output.Append(ch);
                    }
                    break;
                case '"':
                case '\'':
                    output.Append(ch);
                    if (quote.HasValue)
                    {
                        if (!IsEscaped(output, i))
                            quote = null;
                    }
                    else quote = ch;
                    break;
                case ',':
                    output.Append(ch);
                    if (!quote.HasValue)
                    {
                        output.AppendLine();
                        AppendIndent(output, depth);
                    }
                    break;
                case ':':
                    if (quote.HasValue) output.Append(ch);
                    else output.Append(" : ");
                    break;
                default:
                    if (quote.HasValue || !char.IsWhiteSpace(ch))
                        output.Append(ch);
                    break;
            }
        }

        return output.ToString();
    }
}
Posted in

Subtracting Sets

A couple times now I’ve wanted to subtract one set (`HashSet`) from another. `HashSet` has a method ExceptWith that does just this, except that it modifies the current set in place. What if you don’t want that? You need to copy it first.

Or you could use Linq’s Except method, except that it returns `IEnumerable` instead of a `HashSet`. What if you don’t want that? You need to convert it.

So… which method is faster? Let’s find out!

static class Program
{
    public static HashSet<T> ToSet<T>(this IEnumerable<T> collection)
    {
        return new HashSet<T>(collection);
    }

    public static HashSet<T> Subtract<T>(this HashSet<T> set, IEnumerable<T> other)
    {
        var clone = set.ToSet();
        clone.ExceptWith(other);
        return clone;
    }

    static void Main(string[] args)
    {
        var A = new HashSet<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        var B = new HashSet<int> { 2, 4, 6, 8, 10 };
        var sw = new Stopwatch();

        sw.Restart();
        for (int i = 0; i < 1000000; ++i)
        {
            var C = A.Except(B).ToSet();
        }
        sw.Stop();
        Console.WriteLine("Linq: {0} ms", sw.ElapsedMilliseconds);

        sw.Restart();
        for (int i = 0; i < 1000000; ++i)
        {
            var C = A.Subtract(B);
        }
        sw.Stop();
        Console.WriteLine("Native: {0} ms", sw.ElapsedMilliseconds);

        Console.ReadLine();
    }
}

On my computer, this outputs:

Linq: 1291 ms
Native: 756 ms

So, clearly the second method is faster. About 40% for you math types.

I should note that “clone” isn’t really a clone, it’s a shallow copy. Only the container class itself is “cloned”; the elements still refer their originals.

Posted in

String Slice

Here’s an extension method to slice strings in C#, similar to Python’s slice notation.

public static string Slice(this string str, int? start = null, int? end = null, int step = 1)
{
    if (step == 0) throw new ArgumentException("Step size cannot be zero.", "step");

    if (start == null) start = step > 0 ? 0 : str.Length - 1;
    else if (start < 0) start = start < -str.Length ? 0 : str.Length + start;
    else if (start > str.Length) start = str.Length;

    if (end == null) end = step > 0 ? str.Length : -1;
    else if (end < 0) end = end < -str.Length ? 0 : str.Length + end;
    else if (end > str.Length) end = str.Length;

    if (start == end || start < end && step < 0 || start > end && step > 0) return "";
    if (start < end && step == 1) return str.Substring(start.Value, (end - start).Value);

    var sb = new StringBuilder((int)Math.Ceiling((end - start).Value / (float)step));
    for (int i = start.Value; step > 0 && i < end || step < 0 && i > end; i += step)
        sb.Append(str[i]);
    return sb.ToString();
}

"Hello World".Slice(1, -1); // ello Worl
"Hello World".Slice(null, null, -1); // dlroW olleH
Posted in

How to deep-copy/clone an object

The easiest way to deep copy an object is to serialize and deserialize it. Here’s an example from a project I’m working on:

[Serializable()]
public class Board :ICloneable, ISerializable {

    // ...

    object ICloneable.Clone()
    {
        return this.Clone();
    }

    public Board Clone()
    {
        using (var ms = new MemoryStream())
        {
            var bf = new BinaryFormatter();
            bf.Serialize(ms, this);
            ms.Position = 0;
            return (Board)bf.Deserialize(ms);
        }
    }

You might need to implement the serialization functions too for this to work, however.

Posted in

Thread-Safe Observable List for WPF

I’m probably posting this too early; I haven’t had a chance to extensively test it yet but I basically just locked every function down, and made any method that actually modifies the list run on the main thread so that notifications can be sent. It ought to work 🙂

class ObservableList<T> : IList<T>, INotifyCollectionChanged where T : INotifyPropertyChanged
{
    private Dispatcher dispatcher;
    private List<T> list;
    private object sync;

    public ObservableList(Dispatcher dispatcher = null)
    {
        this.dispatcher = dispatcher ?? Dispatcher.CurrentDispatcher;
        this.list = new List<T>();
        this.sync = new object();
    }

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        lock (sync)
        {
            if (CollectionChanged != null)
            {
                CollectionChanged(this, e);
            }
        }
    }

    public int IndexOf(T item)
    {
        lock (sync)
        {
            return list.IndexOf(item);
        }
    }

    public void Insert(int index, T item)
    {
        if (dispatcher.CheckAccess())
        {
            lock (sync)
            {
                list.Insert(index, item);
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
            }
        }
        else
        {
            dispatcher.Invoke(new Action<int, T>(Insert), DispatcherPriority.Send, index, item);
        }
    }

    public void RemoveAt(int index)
    {
        if (dispatcher.CheckAccess())
        {
            lock (sync)
            {
                var item = list[index];
                list.RemoveAt(index);
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
            }
        }
        else
        {
            dispatcher.Invoke(new Action<int>(RemoveAt), DispatcherPriority.Send, index);
        }
    }

    public T this[int index]
    {
        get
        {
            lock (sync) { return list[index]; }
        }
        set
        {
            lock (sync) { list[index] = value; }
        }
    }

    public void Add(T item)
    {
        if (dispatcher.CheckAccess())
        {
            lock (sync)
            {
                list.Add(item);
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
            }
        }
        else
        {
            dispatcher.Invoke(new Action<T>(Add), DispatcherPriority.Send, item);
        }
    }

    public void Clear()
    {
        if (dispatcher.CheckAccess())
        {
            lock (sync)
            {
                list.Clear();
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
        }
        else
        {
            dispatcher.Invoke(new Action(Clear), DispatcherPriority.Send);
        }
    }

    public bool Contains(T item)
    {
        lock (sync) { return list.Contains(item); }
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        lock (sync) { list.CopyTo(array, arrayIndex); }
    }

    public int Count
    {
        get { lock (sync) { return list.Count; } }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        if (dispatcher.CheckAccess())
        {
            lock (sync)
            {
                var index = list.IndexOf(item);
                var result = list.Remove(item);
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
                return result;
            }
        }
        else
        {
            return (bool)dispatcher.Invoke(new Func<T, bool>(Remove), DispatcherPriority.Send, item);
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        lock (sync)
        {
            return list.GetEnumerator();
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

You can simply delete the “where T : INotifyPropertyChanged” if you don’t like that restriction, but I put it there so that you don’t forget that your objects should notify your controls that their properties have changed, so that the GUI gets refreshed properly.

Posted in

Observable Priority Queue

Just started playing around with WPF in VS 2010. They have this ObservableCollection class which you can bind to your DataGrid or ListControl and then when you add or remove items from it, the control is refreshed automatically. However, I wanted to use my PriorityQueue class that I posted about earlier, so I modified it a bit:

class PriorityQueue<TValue> : PriorityQueue<TValue, int> where TValue : INotifyPropertyChanged { }
class PriorityQueue<TValue, TPriority> : IEnumerable<TValue>, INotifyCollectionChanged
    where TValue : INotifyPropertyChanged
    where TPriority : IComparable
{
    private SortedDictionary<TPriority, Queue<TValue>> dict = new SortedDictionary<TPriority, Queue<TValue>>(new ReverseComparer());
    private int count = 0;

    public int Count { get { return count; } }
    public bool Empty { get { return Count == 0; } }

    private class ReverseComparer : IComparer<TPriority>
    {
        public int Compare(TPriority x, TPriority y) { return y.CompareTo(x); }
    }

    public void Enqueue(TValue val, TPriority pri = default(TPriority))
    {
        ++count;
        if (!dict.ContainsKey(pri)) dict[pri] = new Queue<TValue>();
        dict[pri].Enqueue(val);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, val));
    }

    public TValue Dequeue()
    {
        --count;
        var pair = dict.First();
        var queue = pair.Value;
        var val = queue.Dequeue();
        if (queue.Count == 0) dict.Remove(pair.Key);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, val));
        return val;
    }

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (CollectionChanged != null)
        {
            CollectionChanged(this, e);
        }
    }

    public IEnumerator<TValue> GetEnumerator()
    {
        foreach (var queue in dict.Values)
        {
            foreach (var value in queue)
            {
                yield return value;
            }
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Priorities are sorted in descending order (higher value = higher priority).

Also discovered that I could just use “yield return” instead of having to write a custom Enumerator class too! Very nice. Especially since I wouldn’t have known how to write it 🙂

Human-readable file size in C#

static string ReadableFileSize(double size, int unit = 0)
{
    string[] units = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" };

    while (size >= 1024)
    {
        size /= 1024;
        ++unit;
    }

    return String.Format("{0:G4} {1}", size, units[unit]);
}

I made “bytes” a double so you could pass in fractions, which you might get when calculating download speeds.