Framework Tips XI: What is this?

Lately while going through the code of latest MEF release, I stumbled upon a piece of code that used a very little known feature of .NET

Just take a look:

public struct Tuple<TFirst, TSecond>
{
    public Tuple(TFirst first, TSecond second)
    {
        this = new Tuple<TFirst, TSecond>();//looks strange?
        this.First = first;
        this.Second = second;
    }
    //[...]
}

I myself was shocked at first. “Hey! You can’t assign to this! It’s against the nature and common sense.” Then I went to C# language specification to look for explanation and indeed I’ve found it.

The key here is the fact that Tuple is a struct, not a class. As it turns out, the meaning of this differs between those two.

The explanation comes from chapter 11.3.6 – Meaning of this


Within an instance constructor or instance function member of a class, this is classified as a value. Thus, while this can be used to refer to the instance for which the function member was invoked, it is not possible to assign to this in a function member of a class.

Within an instance constructor of a struct, this corresponds to an out parameter of the struct type, and within an instance function member of a struct, this corresponds to a ref parameter of the struct type. In both cases, this is classified as a variable, and it is possible to modify the entire struct for which the function member was invoked by assigning to this or by passing this as a ref or out parameter.

It makes total sense when you think about it, still – I think many experienced people can be surprised by that.

Technorati Tags:

Testing collections with NUnit

How do you test collections for equality of their elements? I often used to write my own custom assert for that, something like:

public void AssertCollectionElementsAreEqual<T>(IEnumerable<T> expected, IEnumerable<T> actual)
{
    var first = expected.GetEnumerator();
    var second = actual.GetEnumerator();
    int count = 0;
    while(first.MoveNext())
    {
        if(second.MoveNext())
        {
            Assert.AreEqual(first.Current,second.Current);
        }
        else
        {
            throw new AssertionException(string.Format("Collection has less elements than expected: {0}", count));
        }
        count++;
    }
    if(second.MoveNext())
    {
        throw new AssertionException(string.Format("Collection has more elements than expected."));
    }
}

I thought it’s just plain to common task to not be included in the framework itself, so I read the manual, and I found CollectionAssert.AreEqual() method that does exactly that.

Then Charlie Poole, made me realize there is even simpler way.

using System.Collections.Generic;
using NUnit.Framework;
 
namespace NUnitAreEqualSample
{
    [TestFixture]
    public class CollectionsEqualitySampleTests
    {
        [Test]
        public void DifferentTypesOfCollectionsShoudBeEqualIfElementsAreEqual()
        {
            var list = new List<string> {"foo", "bar"};
            var array = new[] {"foo", "bar"};
            Assert.AreEqual(list, array);//notice this
        }
    }
}

This produces following result:

nunit_areEqual_passed

Simple Assert.AreEqual() does the job. Sweet.

Technorati Tags: , ,

Framework Tips X: More on enums

Yes, I know that previous Framework Tips had number VIII, but I didn’t notice that I already had VIII, so this makes this part 10th in the row.

Each enum, is a named collection of flags, that mask a numeric type. For example:

public enum ErrorCodes
{
    FileNotFound = 0x12,
    OutOfDiskSpace = 0x14
}

You could use this enum in an error handling method like:

public void HandleError(ErrorCodes errorCode)
{
    switch(errorCode)
    {
        case ErrorCodes.FileNotFound:
            Console.WriteLine("File not found!");
            break;
        case ErrorCodes.OutOfDiskSpace:
            Console.WriteLine("No disk space left!");
            break;
    }
}

Very simple method, that you can now call from other code, like this:

HandleError(ErrorCodes.FileNotFound);

HandleError method however (as well as ErrorCodes enum, but we’ll get to that in a second) has an issue.

You can call it with code like:

HandleError((ErrorCodes)3);

What now? The cast will succeed (remember that enum is just a mask on an int). You should always put a default clause in such switch, to defend yourself from such malicious input.

 

Now, what will happen if I write:

HandleError(default(ErrorCodes));

What is the default value for ErrorCodes enum? If you keep in mind that ErrorCodes is really an int, the answer is obvious – 0. It is even more obvious, if you notice, that 0 is the only value you don’t have to cast explicitly where ErrorCodes is expected!

HandleError(0); //this will compile
HandleError(5); //this will NOT compile
HandleError((ErrorCodes)5); //this will compile just fine

That’s why it’s always a good idea to have meaningful default value for your enums.

public enum ErrorCodes
{
    NoError = 0,
    FileNotFound = 0x12,
    OutOfDiskSpace = 0x14
}

Technorati Tags:

On generics limitations

I wish generics in C# were more powerful. Why this is not legal?

public class ServiceHost<TService> : ServiceHost where TService : class
{
    public ServiceEndpoint AddServiceEndpoint<TServiceInterface>(Binding binding, string address)
        where TService : TServiceInterface
    {
        return AddServiceEndpoint(typeof(TServiceInterface), binding, address);
    }
}

Technorati Tags:

Can you spot a bug?

Can you spot a bug here?

Took me 20 minutes to find it.smile_whatchutalkingabout

 

private List<string> GetLanguages(string path)
{
    var languages = new List<string>();
    if(File.Exists(path))
    {
        using(var reader = new StreamReader(path,_encoding))
        {
            var dscReader = new DscReader(reader);
            while(dscReader.Read())
            {
                string language = dscReader.Item.Language;
                if (!string.IsNullOrEmpty(language) && !language.Contains(language))
                    languages.Add(language);
            }
        }
    }
    return languages;
}
Technorati Tags:

Framework Tips VIII: Enums and Extension Methods

I have somewhat mixed feelings towards enums in C#. On the one hand, they can greatly improve readability of your code, but on the other hand, they are not much more than textual masks on numeric values. You can’t inherit from them, you can’t use enum as generic constraint (for which I see no good reason), and you can’t extend them… Or can you?

With the addition of Extension Methods in C# 3.0 you finally have the tools to put some life in them. Consider you have an enum like this:

public enum Mp3Player
{
    IPodClassic,
    IPodTouch,
    Zune,
    Zen
}

And you want to extend it to, for example, be able to tell if a player was made by Apple.

private static void Verify(Mp3Player player)
{
    if(player.IsMadeByApple())
        Console.WriteLine("It's made by Apple!");
    else
        Console.WriteLine("Someone else made it.");
}

Now, you can see that I call IsMadeByApple() on a Mp3Player instance. Here’s the piece of code that made it possible:

public static class Mp3PlayerExtensions
{
    public static bool IsMadeByApple(this Mp3Player player)
    {
        return player == Mp3Player.IPodTouch ||
               player == Mp3Player.IPodClassic;
    }
}

There’s no magic here, just a plain extension method, but with it, you can greatly improve readability of your code, by extending your enums with helper methods.

 

Beautiful code

Ok, maybe this title is a little bit too catchy. However, I simply love the expressiveness of this little piece of code I wrote today.

   1:          public bool RegisterAll( Assembly assembly, Func<object, bool> isValidMessage )
   2:          {
   3:              if( assembly == null )
   4:              {
   5:                  throw new ArgumentNullException( "assembly" );
   6:              }
   7:              if( isValidMessage == null )
   8:              {
   9:                  throw new ArgumentNullException( "isValidMessage" );
  10:              }
  11:              var messages = from t in assembly.GetTypes()
  12:                             where t.HasAttribute<MessageAttribute>() &&
  13:                                   isValidMessage( t )
  14:                             select t;
  15:              return messages.All( Register );
  16:          }

 

Technorati Tags: ,

Implicit casting of generic classes

Can anyone tell me what am I missing here? Here’s a simple class

public class Mock<TType>

{

    private readonly TType _actual;

 

    public Mock(TType actual)

    {

        _actual = actual;

    }

    public TType Actual

    {

        get { return _actual; }

    }

    public static implicit operator TType(Mock<TType> item)

    {

        return item.Actual;

    }

}

That’s a generic class that defines implicit casting operator to it’s generic parameter, no magic here. The code compiles without warning. Methods like this one:

 

public TType ThisWorks<TType>()

{

    return new Mock<TType>(default(TType));

}

work as well.

What’s even more stunning, whereas this works:

Mock<string> mock1 = _mocks.Mock<string>();

string actual1 = mock1;

This doesn’t:

Mock<ISomethingUseful> mock2 = _mocks.Mock<ISomethingUseful>();

ISomethingUseful actual2 = mock2;

producing error message:

Error    1    Cannot implicitly convert type ‘Mocks.Mock<Mocks.ISomethingUseful>’ to ‘Mocks.ISomethingUseful’. An explicit conversion exists (are you missing a cast?)

Am I missing something here? Why does it say ‘explicit conversion exists’ when I created implicit conversion? Why it doesn’t work for the interface when it works for string?

[UPDATE:]

According to chapter 6.4.4 of C# 3.0 Language specification you just can’t have implicit conversion to an interface. This in yet another time when I hit an invisible wall trying to do something with generics…

And if you thought that

public class MyClass<TType>:TType

{

}

could be a solution: it isn’t – this won’t compile as well.

Technorati Tags: ,

Fighting with events: Rhino.Mocks strongly typed EventRaiser attempt #2

I just spent good few hours trying to fight awkward limitations of .NET framework in regard to generics, events, delegates and expression trees. And I’m actually not much further than when I started. It bothers me: why put artificial limitations in regard to delegates as generic constraints? I wish I could do:

public IEventManager<T1,T2> Metod<T1,T2,TEvent>(TEvent @event) where TEvent: Func<T1,T2>

(this will not compile, can not use delegates as constraints…) or even better:

public IEventManager<T1,T2> Metod<T1,T2,TEvent>(TEvent @event) where TEvent: void delegate(T1,T2)

This seems to ruin my every idea. Even worse, when I looked for help at Expression Trees, I learned that you can’t have assignments in them, so this will not compile:

public event EventHandler<CancelEventArgs> MyEvent;

 

//somewhere else

Expression<Action<EventHandler<CancelEventArgs>>> exp = x=>MyEvent+=x;

Currently I’m trying to find a way to overcome the fact, that you can’t implicitly cast delegate type to another type with same signature. If I succeed It might be possible to write something roughly similar to:

public class Client

{

    public event EventHandler<CancelEventArgs> MyEvent;

 

    private static void Main(string[] args)

    {

        var repository = new XtoffMockRepository();

        var client = new Client();

        var myEventManager =

            repository.Mock(client.MyEvent);

    }

}

 

public class XtoffMockRepository : MockRepository

{

    public IEventManager<TEvent> Mock<TEvent>(TEvent @event)

    {   ...   }

}

 

public interface IEventManager<T>

{   ...   }

This is however still quite far from what I want to accomplish. In an ideal world, IEventManager<T> would have it’s generic parameter being not TEvent (i.e. EventHandler<CancelEventArgs> in this example) but IEventManager<T1,T2>, where it’s parameters correspond to event method’ parameters (object and CancelEventArgs respectively).

[UPDATE]

As I just noticed I call repository.Mock event inside the class that declares event. This is the only place where passing it as a parameter will work, so this solution will not work either.

Technorati Tags: