Thursday, February 21, 2008

How to Control.Invoke an Anonymous Method?

Why won't Control.Invoke accept a delegate, even though it's looking for a Delegate?


This might seem like some semantic gymnastics... but when trying to compile this:

this.Invoke(delegate() { MessageBox.Show("Hello"); });


you'll get:

Argument '1': cannot convert from 'anonymous method' to 'System.Delegate'


which would suggest that a delegate is not a Delegate.

It's not exactly so - the problem is actually that the compiler does not know to what particular subtype of System.Delegate to cast/convert the anonymous method (delegate) to - and it can't create an instance of System.Delegate.

To make the code work, you have to explicitly create an instance of a particular type of a parameterless delegate returning void, e.g.:

this.Invoke(new MethodInvoker(delegate() {MessageBox.Show("Hello"); }));



see: Anonymous methods and Control.Invoke

Wednesday, February 13, 2008

XSD.exe and DebuggerStepThrough

Did you ever try to step into properties of classes generated by XSD.EXE when debugging? It doesn't work, does it? Not even on methods that you might have extended the XSD.EXE's partial classes with!


It is a common practice to generate partial classes from XSD schemas using XSD.EXE, and then extend some of them in another source file.

This all works nice and clean, but XSD.EXE is nasty and decorates all the classes it creates with the DebuggerStepThrough attribute.

That makes the debugger treat not only those parts of the classes that were created by XSD.EXE as 'nondebuggable'; you can't step into you own code (those methods in the class part authored by you), either!

Now, here are three ways to fix this:

  • run a search&replace and get rid of all the DebuggerStepThrough attributes
  • in Visual Studio, go to Tools/Options..., unfold the tree on the left-hand side of the dialog that will appear down to Debugging/General, and then uncheck the box next to 'Enable Just My Code'
    (Note that you will still have to set a breakpoint in the code marked as DebuggerStepThrough, otherwise the debugger will skip over it anyway)
  • stop using XSD.EXE :) (thanks to Marcin for this acute observation)


Well - the choice is yours :)

[see: Disable DebuggerStepThroughAttribute in code generated by xsd.exe?]

 

Tuesday, February 12, 2008

Convert an Array of Integers to an Array of Strings

This is just brilliant!


int[] ints = new int[] { 1, 2, 3, 4 };
string[] strings = Array.ConvertAll(ints, Convert.ToString);
see: Kieran Lynam's Blog

Check a String for Null or Empty

Yes, the method that .NET Framework 2.0 provides is the fastest.


You used to do it this way (I hope :):
if (s == null || s.Length == 0)

Checking the length is faster that comparing to "" or string.Empty, because the length is simply stored together with the string's content on the heap (see: Strings in .NET and C#, 'Memory usage').

.NET Framework 2.0 put the above check into a single static method of string:
if (string.IsNullOrEmpty(s))

For all the doubting Thomases ;) - this guy actually tested it:
String.Empty, null, Length, or String.IsEmptyOrNull

Tuesday, February 5, 2008

]]> Inside CDATA Section

Ever needed to put ]]> inside a CDATA section? Here's how.


Seems like there are two ways actually:

  • escape the '>' character as >
  • split the CDATA section into two sections:
    <![CDATA[A CDATA text with a ]]]]><![CDATA[> in it]]>


 


Cool! (It demanded a little more escaping from me to make the above look as it looks ;) )

Based on: How can I have ']]>' as a text inside CDATA in xml

 

Friday, January 18, 2008

Calling Methods on a Null Reference???

Is it really possible to call a method of a reference pointing to null?


Take a look at this piece of code:

static void Main ( )
{
MySecondType myObject = null;
myObject = myObject.Parse("10");
}




Is it possible to make it actually run and not generate a 'null reference' exception?

Well, as long as you're using .NET 3.5 - it is! :)

The idea is to declare the Parse method as an extension method operating on objects of type MySecondType:


static class MySecondTypeExtensions
{
public static MySecondType Parse ( this MySecondType me, string text )
{
Int32 value = Int32.Parse(text);
return new MySecondType(value);
}

//...
}



As you can see - it does not matter if me points to null - since the method operates on the text parameter only!

So - nothing makes it illegal to call it on myObject - even though myObject point to null :)


The broader context is here:
Inferred Typing with Factory Methods as Extension Methods

Wednesday, November 7, 2007

Could not find file 'Microsoft.Windows.CommonLanguageRuntime, Version=2.0.50727.0'


When the compiler cannot find the Common Language Runtime, you can become confused...


I recently made some uncontrolled move with my mouse while holding down its left button over the Solution Explorer in Visual Studio - it sometimes just happens, you know... (too much coffee???)

Anyway - I knew something happened, because noticed that the window blinked and looked like digesting something for a second or two... I tried to find some file moved into some strange folder or something, but could find anything like that - so I just continued to write code.

And then - after a few minutes, when I hit Ctrl+Shift+B - I got this error:

Could not find file 'Microsoft.Windows.CommonLanguageRuntime, Version=2.0.50727.0'

Excuse me? Come again (I hit Ctrl+Shift+B once more)?!?

Yeah, apparently the CLR had been uninstalled - oh, no problem, happens every other day, right?

Seriously - the error did not want to go away, and (of course) it was the worst moment for something like that to appear, so I started googling... and found out, that it actually does happen - well, not the uninstallation of the CLR, but the error message.

The cause of the error message is this:

If I activate the "Enable ClickOnce Security Settings" [in Project Properties] I get the error, if I disable this feature it compiles correctly.

[http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=148745&SiteID=1]

Perfectly reasonable, eh?

Anyway - the real question is now - what kind of crazy jerk must I have done with my mouse to turn that option on???