.NET Daily Quiz Archive — week 2

I was at TechEd during most of this week so some of the quizzes are a bit half-assed. Sorry.

Daily Quiz #006

using System;
using System.Collections.Generic;
public class Program
{
    static void Main(string[] args)
    {
        var stringFactories = new List<Func>();
        var urls = new List
        {
            new Uri("http://google.com"), new Uri("http://bing.com")
        };
        foreach (var i in urls)
        {
            stringFactories.Add(() => i.ToString());
        }
        foreach (var i in stringFactories)
        {
            Console.WriteLine(i());
        }
    }
}

What is the output of this program when compiled in C# 4.0? What about C# 5.0? Why are they different?

Answer:

In C# 4.0:

http://bing.com
http://bing.com

In C# 5.0:

http://google.com
http://bing.com

Why?
The weird output in C# 4.0 (and all earlier versions going back to 1.0) is cause by the infamous "access to modified closure". The generated compiler output for the first foreach loop looks like

{
	IEnumerator e = ((IEnumerable)urls).GetEnumerator();
	try
	{
		Uri m; // here's your problem
		while(e.MoveNext())
		{
			m = (Uri)e.Current;
			stringFactories.Add(() => i.ToString());
		}
	}
	finally
	{
		if (e != null) ((IDisposable)e).Dispose();
	}
}

Note the Uri m is on the outside of the loop and is reused in each iteration. The problem is that the functions in stringFactories are executed on-demand and contain a closure. The closure includes a reference to that variable m (it is not copied). When m is changed by the enumerator the captured reference still points to the same memory address, so both Funcs end up pointing to the same modified closed variable.

This problem has been fixed in C# 5.0. This is the only breaking change in C# 5.0. If your code relies on this behaviour then either you're an evil genius or you have done something wrong - in either case, you should fix it.

For completeness, here is the generated code from C# 5.0:

{
	IEnumerator e = ((IEnumerable)urls).GetEnumerator();
	try
	{
		while(e.MoveNext())
		{
			Uri m; // much better
			m = (Uri)e.Current;
			stringFactories.Add(() => i.ToString());
		}
	}
	finally
	{
		if (e != null) ((IDisposable)e).Dispose();
	}
}

Now each closure references a fresh variable. For more information check out Eric Lippert's excellent blog post, Closing over the loop variable considered harmful.


Daily Quiz #007

Which is faster? Which uses less memory? Which should you use?

var s = string.Empty;
var s = "";

Answer:

They're the same, as near as makes no difference. Using "" results in a single heap allocation the first time you use it, but due to string interning this never occurs again. It's inconsequential.

Which uses less memory? Again due to string interning it makes no difference. The common misconception is that string.Empty will use less memory because it's a static field while "" will result in an allocation for each use, but interning results in a single allocation for "".

Which should you use? This is the most important bit. Use whichever you like, but establish a convention in your team and stick to it. I agree with some people that "" could be mistaken for " " but honestly with a fixed-width font I don't see it happening.

If you haven't read about string interning and you are working on an application that does a lot of string allocation/manipulation then I strongly recommend you Google it on Bing.


Daily Quiz #008

public struct Foo {
  public int i;
  public string j;
  public double k;
}
public class Program {
  public static void Main(string[] args) {
    IEnumerable foos = ReadFooFile();
    Foo referenceFoo = ReadReferenceFoo();
    foreach (var f in foos) {
      if (f.Equals(referenceFoo)) {
        Console.WriteLine("Bar");
      }
    }
  }
  // other methods
}

Why is my application so slow? What is one very simple thing I can do to speed it up?

Answer:

The default override for value types of object.Equals uses reflection to compares each field individually. This is a major performance problem if you are comparing a large number of value types. The default implementation for object.Equals on reference types is a simple reference equality.

For more details check out my old blog post (shameless plug).


Daily Quiz #009

Today's daily quiz brought to you by a real-life situation faced by a colleague. This one is tricky but important.

public partial class MainWindow : Window
{
    TaskScheduler _ui;
    public MainWindow()
    {
        InitializeComponent();
        _ui = TaskScheduler.FromCurrentSynchronizationContext();
        Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }
    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Task.Factory.StartNew(() =>
        {
            DoLongOperation();
        })
        .ContinueWith(t =>
            {
                DoQuickOperation();
                Task.Factory.StartNew(() =>
                {
                    DoLongOperation();
                });
            }, _ui);
    }
    // etc...
}

When we execute this code we find that the first call occurs in a background thread as expected, but the second call (nested inside a continuation) occurs on the UI thread and blocks the UI. Why? How can we resolve this?

Answer:

(This answer comes directly from a co-worker, Ben Fox. His explanation was better than my prepared one).
We're explicitly specifying a TaskScheduler which was created from the UI Synchronization Context in the first ContinueWith call, the Tasks library is helpfully re-using that context for further tasks created within that context.

It’s a feature, not a bug! (but I’m not sure why — seems unintuitive to me).

You can override this behaviour in subsequent nested calls to Task.Factory.StartNew by passing it TaskScheduler.Default, which will cuse the task to be scheduled on (I believe) the thread pool.
Read more.

And here's the correct code I prepared:

public partial class MainWindow : Window
{
    TaskScheduler _ui;
    // Store the default scheduler up front
    TaskScheduler _backgroundScheduler = TaskScheduler.Default;
    public MainWindow()
    {
        InitializeComponent();
        _ui = TaskScheduler.FromCurrentSynchronizationContext();
        Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }
    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Task.Factory.StartNew(() =>
        {
            DoLongOperation();
        })
        .ContinueWith(t =>
            {
                DoQuickOperation();
                Task.Factory.StartNew(() =>
                {
                    DoLongOperation();
                }, CancellationToken.None, TaskCreationOptions.None, _backgroundScheduler);
            }, _ui);
    }
    // etc...
}


Daily Quiz #010

using (var proxy = new MyWcfServiceProxy())
{
    proxy.Open();
    var result = proxy.MyServiceMethod();
    proxy.Close();
}

What have I done wrong?

Answer:

WCF clients should generally not be wrapped in using blocks because a faulted service channel will throw an exception when Close() is called (which is implicitly called by Dispose()).

If you really want to use using blocks for your WCF service clients then check out this excellent article. Otherwise, here is one correct way of managing a WCF service client.

public class CommunicationWrapper : IDisposable
    where T : ICommunicationObject
{
    private readonly T _object;
    public T Object
    {
        get { return _object; }
    }
    public CommunicationWrapper(T communicationObject)
    {
        _object = communicationObject;
    }
    public void Dispose()
    {
        ServiceUtils.Dispose(Object);
    }
}
public static class ServiceUtils
{
    public static void Dispose(ICommunicationObject communicationObject)
    {
        if (communicationObject != null)
        {
            try
            {
                if (communicationObject.State != CommunicationState.Faulted)
                    communicationObject.Close();
                else
                    communicationObject.Abort();
            }
            catch (CommunicationException)
            {
                communicationObject.Abort();
            }
            catch (TimeoutException)
            {
                communicationObject.Abort();
            }
            catch (Exception)
            {
                communicationObject.Abort();
                throw;
            }
        }
    }
}