Static predicates, delegate inference and performance
C# 2.0 introduced a feature called delegate inference. Delegate inference is an simplification of how you initialize delegates.
Where you prior to C# 2.0 would have to write:
MyDelegate d = new MyDelegate(MyFunction);
You can now simply write:
MyDelegate d = MyFunction;
The two lines of code behaves exactly the same. They construct a new instance of MyDelegate passing MyFunction as argument to the constructor, and then assign the instance to the variable d.
As the name ‘delegate inference’ suggests, the compiler fills in the ‘missing parts’ using inference, leaving the developer with less keystrokes and more readable code. Which is a good thing.
There is a problem with this syntax, though. Looking at this code might lead the developer to think that this is a simple assignment. It looks like we’re just assigning one delegate to another, or for the C++ developer, that we’re just initializing a simple function pointer. But we’re not - we’re also invoking a constructor and placing an object on the heap.
Now, in most cases this isn’t a big problem, but there are times when you could do without this overhead; when your delegate function is static.
Take a look at this predicate example:
string s = "123"; bool b = Array.TrueForAll(s.ToCharArray(), Char.IsDigit);
This exmaple uses the Array.TrueForAll function, with Char.IsDigit as its predicate, to determine if the characters in the string are all digits. When the compiler deducts the proper delegate for Char.IsDigit the code is interpreted like this:
string s = "123"; bool b = Array.TrueForAll(s.ToCharArray(), new Predicate<Char>(Char.IsDigit));
As you can see this code will create a new Predicate instance every time it’s called. As Char.IsDigit is a static function it will behave the same no matter how many delegates that reference it. In other words you won’t ever need more than one.
This leads me to suggest a small optimization - to make the delegate itself static (which in my opinion should have been done by the compiler):
// the inference and construction is done here static Predicate<Char> IsDigitPredicate = Char.IsDigit;
This would reduce the overhead of creating the unnecessary delegates, and you can use this in all calls where the Char.IsDigit is used as a predicate:
string s = "123"; bool b = Array.TrueForAll(s.ToCharArray(), IsDigitPredicate);
By itself this is a small optimization, but if you use the predicate a lot then the reduced overhead could make a difference.












