Monday, November 12, 2007

Faster Device Emulator in Visual Studio 2005

Hurray! There is a new and faster Device Emulator in Visual Studio 2005. Deployment and debugging of .NET Compact Framework apps used to be very slow and tiring. Some bugs were fixed and deployment is significantly faster in Device Emulator ver. 2.0 (download here). Installer will replace the old version in your Visual Studio.

Friday, September 21, 2007

Boxing Mystery in Overloaded and Overridden Method

Recently I have produced a code with strange behaviour in my real C# project. Look at this code:

class BaseMystery

{

  public virtual void Foo(int i) { }

}

 

class Mystery : BaseMystery

{

  private void Foo(object i)

  {

    Console.WriteLine("Finished.");

  }

 

  public new void Foo(int i)

  {

    Foo(i);

  }

}

 

static void Main(string[] args)

{

  Mystery mystery = new Mystery();     

  mystery.Foo(3);

}


It produces:

Process is terminated due to StackOverflowException.


There is nothing strange. The method Mystery.Foo(int) is called repeatedly. Then I replaced hidding method Mystery.Foo(int) by overriding method:

class BaseMystery

{

  public virtual void Foo(int i) { }

}

 

class Mystery : BaseMystery

{

  private void Foo(object i)

  {

    Console.WriteLine("Finished.");

  }

 

  public override void Foo(int i)

  {

    Foo(i);

  }

}

 

static void Main(string[] args)

{

  Mystery mystery = new Mystery();     

  mystery.Foo(3);

}


And the output is:

Finished.


Hah! What is the matter? Let us go to explore IL code of method Mystery.Foo(int):

public new void Foo(int)


.method public hidebysig instance void Foo(int32 i) cil managed

{

  .maxstack 8

  L_0000: nop

  L_0001: ldarg.0

  L_0002: ldarg.1

  L_0003: call instance void BoxingMystery.Program/Mystery::Foo(int32)

  L_0008: nop

  L_0009: ret

}


and

public override void Foo(int)


.method public hidebysig virtual instance void Foo(int32 i) cil managed

{

  .maxstack 8

  L_0000: nop

  L_0001: ldarg.0

  L_0002: ldarg.1

  L_0003: box int32

  L_0008: call instance void BoxingMystery.Program/Mystery::Foo(object)

  L_000d: nop

  L_000e: ret

}


Argument i has been boxed. Why? I would expect that the IL body of method Mystery.Foo(int) will be the same in new and override declaration but it is different. It is very strange behaviour of compiler. What is your explanation?

Overridded method in my real project was the right one. In addition, I renamed the methods, because my colleagues could be confused like me.

kick it on DotNetKicks.com

Monday, September 17, 2007

Launch NUnit Tests directly from Visual Studio and Debug

Launching tests directly from Visual Studio is very comfortable feature. Developers, who are familiar with test driven development, need to launch tests frequently, so this feature is necessary for them.

My favourite testing framework is NUnit. Tests in this framework are launched from external application with perfect GUI.

In this article I will demonstrate how to start external application from Visual Studio, e.g. NUnit GUI, and keep running debugger. Debugging NUnit tests is very significant advantage because standard GUI of NUnit framework does not support it.

So, suppose that you have created a class library project with the following NUnit test:

using System.IO;

using NUnit.Framework;

using NUnit.Framework.SyntaxHelpers;

 

namespace DirectNUnit

{

  [TestFixture]

  public class Tests

  {

    [Test]

    public void Test()

    {

      string combinedPath = Path.Combine(@"C:\Projects", @"HelloWorld");

      Assert.That(combinedPath, Is.EqualTo(@"C:\Projects\HelloWorld"));

    }

  }

}



Now, you want to start this test directly from Visual Studio and use some breakpoints in the test. You can do it without any VS plug-in, just edit project settings. Open Project | Properties | Debug and set values like this:



Enter Start external program and Command line arguments, that is the path to the assembly containing your test.

For launching NUnit GUI and debugging tests press F5.

kick it on DotNetKicks.com

Monday, June 11, 2007

Currency Format Depending on Culture

It is usual, that you write an application with GUI for a specified culture and then you suddenly get to know that the application should work with several different currency formats. In the following example I want to demonstrate a very simple method how to change the currency format in your application elegantly and dynamically.

Ordinarily numbers are formatted as currency by these ways:

decimal value = 1234567.89M;

Console.WriteLine(value.ToString("C"));

//or

Console.WriteLine("{0:C}", value);

//or

Console.WriteLine(String.Format("{0:C}", value));


Actually, there are many places like this in your application and you want to change the format depending on user's choice of culture. The following code comes in handy:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-us");


The whole example is:

using System;

using System.Threading;

using System.Globalization;

 

namespace CurrencyFormat

{

  class Program

  {

    static void Main()

    {

      decimal value = 1234567.89M;

      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

      Console.WriteLine("{0:C}", value);

      Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");

      Console.WriteLine("{0:C}", value);     

      Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");

      Console.WriteLine("{0:C}", value);

    }

  }

}


Output:

$1,234,567.89

1 234 567,89 €

Y1,234,568


List of all available culture names and identifiers is on MSDN.

kick it on DotNetKicks.com

Thursday, May 24, 2007

Syntax-Highlighted Code from Visual Studio as HTML

Maybe you wondered about syntax-highlighted code in this blog but blogger.com does not provide any tool for this. If you use Visual Studio, just try this CopySourceAsHtml add-in.

CopySourceAsHtml generates HTML source of your syntax-highlighted code in VS. You can select and copy your code as HTML to clipboard, so your syntax-highlighted code can be placed anywhere.

Here are my settings of CopySourceAsHtml add-in:


My "File Style" is:

border:1px solid black;

padding: 8pt;

width: 94%;

overflow: auto;

background-color: #F0F0F0;


Here is an example output:

using System;

 

class HelloWorld

{

  static void Main()

  {

    Console.WriteLine("Hello, World!");   

  }

}



kick it on DotNetKicks.com

Wednesday, May 23, 2007

OpenGL in .NET

There is a very simple way how to use OpenGL library in .NET application using C#. The library what you need can be downloaded here csgl.sourceforge.net. The simplest way is to add these downloaded files to your project:

  • csgl.dll
  • csgl.native.dll
See the following "Hello world!" project step by step.

Create a new Windows application project. In the new solution add a new project Class library named GLViewControl. Add csgl.dll and csgl.native.dll to the GLViewControl project and reference csgl.dll library. Reference also System.Windows.Forms and System.Drawing.
Set the "Copy to output directory" property for csgl.native.dll file. Presence of this file in the output directory is important unless you have to install csgl on each system particularly.

Now the project is ready for our code. Add a new class in GLViewControl:

using System;

using CsGL.OpenGL;

 

namespace GLViewControl

{

  public class GLView : OpenGLControl

  {

    public override void glDraw()

    {

      GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);// Clear the Screen and the Depth Buffer

      GL.glMatrixMode(GL.GL_MODELVIEW); // Modelview Matrix

      GL.glLoadIdentity();              // reset the current modelview matrix   

      GL.glTranslatef(0.0f, 0.0f, -4.0f); 

 

      GL.glBegin(GL.GL_POLYGON);

        GL.glColor3d(0, 0, 1);

        GL.glVertex3f(-1, -1, 0);

        GL.glColor3d(0, 1, 0);

        GL.glVertex3f(1, -1, 0);

        GL.glColor3d(1, 0, 0);

        GL.glVertex3f(0, 1, 0);

      GL.glEnd();

    }

 

    protected override void InitGLContext()

    {     

      GL.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // black background

      GL.glClearDepth(1.0f);                  // depth buffer setup

      GL.glEnable(GL.GL_DEPTH_TEST);          // enables depth testing

      GL.glDepthFunc(GL.GL_LEQUAL);            // type of depth testing

      GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);  // nice perspective calculations           

    }

 

    protected override void OnSizeChanged(EventArgs e)

    {

      base.OnSizeChanged(e); 

      GL.glMatrixMode(GL.GL_PROJECTION);

      GL.glLoadIdentity();

      GL.gluPerspective(45.0f, (double)Size.Width / (double)Size.Height, 0.1f, 100.0f);

      GL.glMatrixMode(GL.GL_MODELVIEW);

      GL.glLoadIdentity();

    }

  }

}



And now just drag and drop a new GLView control from the toolbox in VS on your form and run the application. The result looks like this:



kick it on DotNetKicks.com

Wednesday, May 16, 2007

User Defined Aggregate Function in SQL for String Concatenation using CLR

If you tried to concatenate strings from group in SQL, probably you would start looking for an aggregate function similar to SUM or COUNT. There is no function like this in SQL Server 2005 and even further there is no way how to create a custom aggregate function using SQL. You can use just built-in aggregates.

Fortunately, SQL Server 2005 integrates common language runtime (CLR). So, the solution is to write an aggregate function in C# and include it among built-in functions in SQL Server.

Let us show an example with aggregate function for strings concatenation. At first you should create a new project in VS - use template Class Library, name it for example MyCLRLib.

The key methods are:

  • Init() - initializes private variables
  • Accumulate() - appends the next value
  • Merge() - merges partial aggregates
  • Terminates() - returns a result aggregation
Here is completed a copy-paste code:

using System;

using System.Text;

using System.IO;

using Microsoft.SqlServer.Server;

using System.Data.SqlTypes;

 

[Serializable]

[SqlUserDefinedAggregate(

    Format.UserDefined,        //use custom serialization to serialize the intermediate result

    IsInvariantToNulls = true//optimizer property

    IsInvariantToDuplicates = false, //optimizer property

    IsInvariantToOrder = false, //optimizer property

    MaxByteSize = 8000)        //maximum size in bytes of persisted value

]

public class Concatenate : IBinarySerialize

  // Intermediate result data of concatenation

  private StringBuilder intermediateResult;

 

  public void Init()

  {

    this.intermediateResult = new StringBuilder();

  }

 

  // If the next value is not null, append it to the end of string

  public void Accumulate(SqlString value)

  {

    if (value.IsNull)

    {

      return;

    }

    this.intermediateResult.Append(value.Value).Append(", ");

  }

 

  //Merges the partial aggregate with this aggregate

  public void Merge(Concatenate part)

  {

    this.intermediateResult.Append(part.intermediateResult);

  }

 

  //Returns the result of the aggregation when finished

  public SqlString Terminate()

  {

    string result = string.Empty;   

    if (this.intermediateResult != null

        && this.intermediateResult.Length > 0)

    {

      result = this.intermediateResult.ToString(0, this.intermediateResult.Length - 1);

    }

 

    return new SqlString(result);

  }

 

  public void Read(BinaryReader reader)

  {

    intermediateResult = new StringBuilder(reader.ReadString());

  }

 

  public void Write(BinaryWriter writer)

  {

    writer.Write(this.intermediateResult.ToString());

  }

}


Now you can register this function in SQL Server. First of all, enable .NET CLR code execution in your SQL Server:

EXEC sp_configure 'clr enabled', 1;

RECONFIGURE WITH OVERRIDE;

GO


and then create new aggregate function from your compiled assembly:

CREATE ASSEMBLY MyCLRLib FROM 'D:\MyCLRLib.dll'

GO

CREATE AGGREGATE Concatenate (@input nvarchar(1000)) RETURNS nvarchar(max)

  EXTERNAL NAME MyCLRLib.Concatenate

GO


Now you can write:

SELECT Surname, dbo.Concatenate(FirstName)

FROM Families

GROUP BY Surname



kick it on DotNetKicks.com

Tuesday, May 15, 2007

Regular Expressions in .NET

There are powerful tools in Unix such as grep, sed etc. These programs make use of regular expressions - regexp. Luckily, .NET contains a very useful class - a Regex class in a System.Text.RegularExpressions namespace.

Before using of regular expressions you need to understand the syntax. Here is a basic:














.Matches any single character
^Matches the beginning of a string
$Matches the end of a string
*Matches the preceding character or subexpression zero or
more times
+Matches the preceding character or subexpression one or
more times
( )subexpression

For more information about regular expressions syntax see this link

Now I can show how it is being used. The key method is Regex.IsMatch():

Regex regex = new Regex("^a...b$");

bool test1 = regex.IsMatch("axyzb");    //true

bool test2 = regex.IsMatch("axyzxyzb"); //false

bool test3 = regex.IsMatch("d");        //false



The following example validates an e-mail adress:

using System.Text.RegularExpressions;

 

class EmailAdress

{

  static Regex emailRegex = new Regex( @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");

  public static bool Validate(string email)

  {

    return emailRegex.IsMatch(email);

  }

}



For more information see:

.NET Framework Regular Expressions (MSDN)
System.Text.RegularExpressions Namespace (MSDN)

kick it on DotNetKicks.com

Friday, May 11, 2007

Simple Serialization and Deserialization in C#

.NET provides a functionality for storing and loading objects. This post shows how it can be used. The mechanism is called serialization and its purpose is to convert any object to stream of bytes that can be saved on a disk, sent by a protocol via internet etc.

So, at the beginning you have a class which you want to serialize. For example it looks like this:

public class MyExampleClass

{

  public string name;

  public int age;

  public readonly DateTime dateOfBirth;

  public double[] score;

  public MyExampleClass(string name, int age, DateTime dateOfBirth)

  {

    this.name = name;

    this.age = age;

    this.dateOfBirth = dateOfBirth;

    this.score = new double[0];

  }

}


Now, you want to save object of this class on a disk. At first add some namespaces:

using System.IO;    //Stream class

using System.Runtime.Serialization.Formatters.Binary;



Add [Serializable] attribute to your class:

[Serializable]

public class MyExampleClass



and then add methods for save and load in MyExampleClass:

public void SaveToFile(string filename)

{

  using (Stream stream = File.Open(filename, FileMode.Create))

  {

    BinaryFormatter formatter = new BinaryFormatter();

    formatter.Serialize(stream, this);

  }

}

 

public static MyExampleClass LoadFromFile(string filename)

{

  using (Stream stream = File.Open(filename, FileMode.Open))

  {

    BinaryFormatter formatter = new BinaryFormatter();

    return (MyExampleClass)formatter.Deserialize(stream);

  }

}



Here is an example how to use these methods:

//create new object

MyExampleClass myObject = new MyExampleClass("John", 30, new DateTime(1967, 1, 1));

myObject.score = new double[] { 5.5, 5.6, 6.1 };

myObject.SaveToFile("store");

 

myObject = null; //discard object

 

//load saved object

myObject = MyExampleClass.LoadFromFile("store");

Console.WriteLine(myObject.name);



That is all. It is very simple to use.

Note: Instead of BinaryFormatter you can use SoapFormatter.
The code is the same, only replace BinaryFormatter by SoapFormatter and use System.Runtime.Serialization.Formatters.Soap namespace. For this namesapce you have to add reference to System.Runtime.Serialization.Formatters.Soap.dll assembly in your project.

The difference is in the saved file. With SoapFormatter you get a file that is human readable. For our example, the saved file contains:

<a1:MyExampleClass id=\"ref-1\">

  <name id=\"ref-3\">John</name>

  <age>30</age>

  <dateOfBirth>

    1967-01-01T00:00:00.0000000+01:00

  </dateOfBirth>

  <score href=\"#ref-4\"/>

</a1:MyExampleClass>

<SOAP-ENC:Array id=\"ref-4\" SOAP-ENC:arrayType=\"xsd:double[4]\">

  <item>5.5</item>

  <item>5.6</item>

  <item>6.1</item>

</SOAP-ENC:Array>



Notice how the reference-typed objects are stored.

Anyone can change the content of this file and the object will reflect these changes after deserialization.

kick it on DotNetKicks.com

Sunday, May 6, 2007

NDoc for .NET 2.0

Very popular NDoc Code Documentation Generator for .NET does not supprot .NET assemblies 2.0. There is a very good unofficial tool for .NET 2.0 by Kevin Downs. You can find more information on this website. I have already tried it and it works very good.

Download NDoc 2.0 Alpha