Feeds:
Posts
Comments

Archive for the ‘CLR/.NET BCL’ Category

There was a recent thread in the MSDN forums where someone was concerned about the behavior of Type.GetElementType. His example was similar to the following:

char [][,][] arr = new char[2][,][];
Console.WriteLine(arr.GetType().GetElementType());

The output he got was:

System.Char[][,]

This puzzled him no end because the element type is clearly char[,][]. He was wondering if this was a bug in GetElementType or even if it was a bug in the C# compiler (incorrectly parsing the array declaration).

Well there is no mystery here. Array types (or rather the runtime type for an array) have a ToString implementation that displays the array using a display format closely resembling the IL syntax for arrays, and not the C# syntax. This is very easily verified with the following code:

Console.WriteLine(typeof(char[][,][,,]));

The output here is:

System.Char[,,][,][]

This is a good idea since the C# array syntax is not universal among CLI languages anyway. Both VB.NET and C++/CLI use array syntax that’s different from this.

Read Full Post »

In .NET 4.0, arrays implement IStructuralEquatable which lets you equate two arrays based on their contents.

int[] array1 = new int[] { 3, 5, 9 };
int[] array2 = new int[] { 3, 5, 9 };

IStructuralEquatable equatableArray1 = array1;
Console.WriteLine(
    equatableArray1.Equals(
        array2, EqualityComparer<int>.Default));

The above code outputs True. You can use it with your custom types too :

class Person : IEquatable<Person>
{
    public string Name { get; set; }

    public int Age { get; set; }

    public bool Equals(Person other)
    {
        return this.Name == other.Name && this.Age == other.Age;
    }
}

var person1 = new[]
{
    new Person() { Name = "John", Age = 17 },
    new Person() { Name = "Alice", Age = 18 }
};

var person2 = new[] {
    new Person() { Name = "John", Age = 17 },
    new Person() { Name = "Alice", Age = 18 }
};

IStructuralEquatable equatablePersonArray1 = person1;
Console.WriteLine(
    equatablePersonArray1.Equals(
        person2, EqualityComparer<Person>.Default));

Read Full Post »

I just published an article on a generic Trictionary class :

The article describes a Trictionary class that is essentially a dictionary except that for each key there are two values, both of differing types. In many cases instead of doing this, the proper approach would most likely to use a struct that would have those two types as members. But there may also be scenarios where you may want to avoid having to unnecessarily create a struct just for this purpose. You could also use an anonymous type, but that’s really not so different in the sense you still end up having a new type in your assembly. Read the article for more info.

Note that the article was inspired by another Trictionary article on Code Project submitted by Joe Enos.

Read Full Post »

Once in a while you have people complaining in the forums that their .NET applications are not releasing memory but that if they minimize the app and restore it, then the memory usage goes down. Why this happens is explained in this Microsoft KB article :

You can simulate this in your code too (under extreme conditions when you really need the memory). In my case I had to do this in an app that loaded very large PNG files – once in a while we’d get a memory exception and then I’d call this method and retry and it would work. It does sound a bit hack-ish but there was nothing else we could do.

[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize",
  ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
private static extern int SetProcessWorkingSetSize(
  IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);

public static void ReleaseUnusedMemory()
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    SetProcessWorkingSetSize(
        System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
}

I thought it’d be nice to post this here in case anyone else ever needs this.

Read Full Post »

I am writing this blog entry as a reminder to myself to be careful when using static fields or properties, and I wanted to document some silliness on my part for posterity. Recently I was working on some code where I wanted to keep track of derived class instances by storing them in a static list in the base class. The classes I was working on were non-trivial and fairly complex (and the original versions were not even authored by me). So for the sake of this blog entry, I’ve come up with simplified base and derived classes to explain what happened. Here’s what the base class looked like :

class Base
{
    private static List list = new List();

    public static List List
    {
        get { return Base.list; }
    }

    private Base()
    {
        Base.list.Add(this);
    }

    public string Name { get; private set; }

    public Base(string name) : this()
    {
        this.Name = name;
    }
}

And here’s what a typical derived class would be like :

class Derived : Base
{
    public static Derived Nish = new Derived("Nish");
    public static Derived Andrew = new Derived("Andrew");
    public static Derived Megan = new Derived("Megan");

    public Derived(string name) : base(name)
    {
    }
}

I thought it was all good, and then ran some code that did an iteration of the list :

foreach (Base item in Derived.List)
{
    Console.WriteLine(item.Name);
}

To my tremendous surprise nothing came up and the list was empty. For a full 10 minutes, the idiot that I am, I kept pondering over this and wondering what the heck was going on. Then it hit me just like that. Even though I was accessing Derived.List, that was just a C# syntactic convenience that allowed me to write it that way because Derived did not have a List member at all (the compiler auto-fixes this to Base.List in the generated MSIL). The property was defined on Base, and thus Derived has not been accessed yet when I iterate Derived.List. So Derived‘s static initialization has not even happened yet. Once I realized my folly, fixing it was straight forward, I had to bring down the List property to the Derived class. This meant that every derived class had to do that which was a bit of an annoyance but not so much as to be a show stopper. Here’s the correct code (for my simplified example) :

class Base
{
    protected static List list = new List();

    private Base()
    {
        Base.list.Add(this);
    }

    public string Name { get; private set; }

    public Base(string name) : this()
    {
        this.Name = name;
    }
}

class Derived : Base
{
    public static Derived Nish = new Derived("Nish");
    public static Derived Andrew = new Derived("Andrew");
    public static Derived Megan = new Derived("Megan");

    public Derived(string name) : base(name)
    {
    }

    public static List List
    {
        get { return Base.list; }
    }
}

Next time you are using static properties in your base classes, just be a little careful – I know I’ll be.

Read Full Post »

I was reviewing some code and found that there were a few enum types that did not have a None value (which is a recommended practice). I thought I’d go ahead and add the None values when I found that the enum values were being written to the database via calls to Convert.ToInt32. Of course this meant that I could not add a None member as the first value since it’d break the database. If all of the enum members specified explicit int values I probably could still add a None member, but even that is kinda messy.

My recommendation is to store enums as strings in the database. Now you can change the order of the members, add and remove members etc. with absolutely no issues. Converting between an enum value and its string name is rather trivial too.

Read Full Post »

Recently at work I had to use the TypeDescriptionProvider attribute while prototyping some new features for our product, and I thought it would be a good idea to demonstrate how to use this attribute and its related classes by writing an article.

Read Full Post »

Older Posts »

Follow

Get every new post delivered to your Inbox.