Thursday, April 26, 2012

Private const

Some odd attribute defining behavior.

Let's define a class with some constants:

class Foo

{
       public const string String = "some string";
       protected const Type Type = null;
       private const int Int = 42;
}

It's strange but you can access these constants in attribute definition, even protected and public, even without class name specialized!

[MyAttribute(String, Int, Type)]
class Foo
{
       public const string String = "some string";
       protected const Type Type = null;
       private const int Int = 42;
}

class MyAttribute :Attribute
{
       public MyAttribute(string someString, int someInt, Type someType)
       {             
       }
}

Note, that Type constant could be set to null only, because constant initializer must be compiler-time constant and even typeof(Foo) is not a compile-time constant. But it is possible to use typeof(Fooin attribute definition:


[MyAttribute(StringInt typeof(Foo))]
class Foo
{
       public const string String = "some string";
       protected const Type Type = null;
       private const int Int = 42;
}


MyMacro

How to fix Visual Studio Macros IDE crashing from here:


2.1.7 On computers on which Visual Studio 2008 or SQL Server 2008 is installed and Visual Studio 2010 has been uninstalled and then reinstalled, using the Visual Studio Macros IDE may cause Visual Studio to crash

Uninstalling Visual Studio 2010 also removes the Visual Studio Macro Tools package. If the computer also has Visual Studio 2008 or SQL Server 2008, then reinstalling Visual Studio 2010 does not reinstall the Visual Studio Macro Tools package. This causes an error when the Macros IDE is started, and Visual Studio crashes if you try to recreate the MyMacros.vsmacros project.
To resolve this issue:
  1. Delete the following file:
    •     On a 64-bit operating system: "%ProgramFiles(x86)%\Microsoft Visual Studio 9.0\Common7\IDE\1033\Microsoft.VSDesignerUI.dll"
    •     On a 32-bit operating system: "%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\1033\Microsoft.VSDesignerUI.dll"
  2. On the Add or Remove programs page, select Uninstall/Change Visual Studio 2010 and then click Next.
  3. Select Add or Remove features.
  4. Clear and then re-select any of the features in the list.  This causes the update state to be enabled.
  5. Finish the Setup wizard. Visual Studio Macro Tools should be installed.

Wednesday, April 25, 2012

Tail recursion

Some odd behavior to keep in mind.

The following code is expected to fail with StackOverflowException:


class Program
{
       static void Main(string[] args)
       {
              Tail();
       }

       private static void Tail()
       {
              Tail();
       }
}

And it actually fails in all build configuration, except "Release - x64". In this configuration .NET 4 enables the tail recursion optimization, so the Tail() function just hangs.


You can find more info about tail recursion optimization here.

Monday, April 9, 2012

Lazy tree

Some stupid task about Expression trees.

Write down a simplest expression tree visitor (inherited from System.Linq.Expressions.ExpressionVisitor) that will have a static method:

public static IEnumerable<Expression> All(Expression node)

This method should return lazy enumeration of all expression in a an expression tree represented by node. By "lazy" I mean that a tree should not be entirely flattered into a list like this:


class NonLazyVisitor : ExpressionVisitor
{
       readonly List<Expression> _nodes = new List<Expression>();
       public static IEnumerable<Expression> All(Expression node)
       {
              var visitor = new NonLazyVisitor();
              visitor.Visit(node);
              return visitor._nodes;
       }
       public override Expression Visit(Expression node)
       {
              _nodes.Add(node);
              return base.Visit(node);
       }
}


This visitor will traverse entire expression tree - the Visit() method will be called on every node regardless of how much nodes I really want to visit. The task is to minimize the footprint and visit as less nodes as possible.

The lazy visitor should return expressions in the same order as NonLazyVisitor above.

Thursday, October 27, 2011

Serialization lost

Just a side note.

When an object is been deserialized by IFormatter, no constructors are called*! So if you have any fields marked as [NonSerialized] that are initilized in constructors or inline, they would not be initialized at all!

Consider the following example:

[Serializable]
public class Test
{
 public Test()
 {
  Console.WriteLine("Inside ctor");
 }

 [NonSerialized]
 private readonly string _nonSerizlied = "Non serialized";

 private readonly string _serizlied = "Serialized";

 public override string ToString()
 {
  return string.Format("NonSerizlied: {0}, Serizlied: {1}"_nonSerizlied_serizlied);
 }
}
 
 
static void Main(string[] args)
{
 Test test = new Test();

 Console.WriteLine(test);

 IFormatter formatter = new BinaryFormatter();
 using (var stream = new MemoryStream())
 {

  formatter.Serialize(stream, test);

  stream.Position = 0;

  test = (Test) formatter.Deserialize(stream);

  Console.WriteLine(test);
 }
} 
 
The output will be:

Inside ctor
NonSerizlied: Non serialized, Serizlied: Serialized
NonSerizlied: , Serizlied: Serialized

So _nonSerizlied  field is not initialized at all and constructor is not called.

* If a type realized ISerializable, the serialization constructor will be called, but the default one will be not as well.


 

Wednesday, October 26, 2011

Initialization trick

You all now the cool syntax sugar for object initialization in C#:

var item = new Item { Age = 5 };


Also there are sugar for collection initialization:

var items = new List<Item> { new Item { Age = 5 } };

And, of course, we could mix these two cases:
class ItemContainer
{
    public List<Item> Items{get;set;}
} 

// ...

var itemContainer = new ItemContainer {
   Items = new List<Item> {new Item { Age = 5 }}
};

But there is one rarely used case that is even cooler. If  ItemContainer.Items is ICollection and it is created in constructor:
class ItemContainer
{
   public ItemContainer()
   {
      Items = new List<Item>();
   } 
  
   public List<Item> Items{get;set;}
} 
 
Than you can add elements to the Items collection without 'new' construction:
var itemContainer = new ItemContainer {
   Items = { new Item { Age = 5 } }
};

This code will be ILed as:

IL_0000: newobj ItemContainer..ctor
IL_0005: stloc.1 
IL_0006: ldloc.1 
IL_0007: callvirt ItemContainer.get_Items  
IL_000C: newobj Item..ctor
IL_0011: stloc.2 
IL_0012: ldloc.2 
IL_0013: ldc.i4.1 
IL_0014: callvirt Item.set_Age
IL_0019: ldloc.2 
IL_001A: callvirt System.Collections.Generic.List<Item>.Add

So there is no constructions of Items, just single method 'Add'.
The same is applicable for Expressions as well.

Wednesday, September 28, 2011

Only one

Just another LINQ puzzle.

Let's assume that we have sequence of objects of type Item:

class Item
{
   public int Age{get;set;}
}

How could you return all objects from the sequence that have Age value maximized (in a single LINQ query and single enumeration of the sequence)?

If the question was about returning the first object, the answer is straightforward:

return items.OrderByDescending(x=>x.Age).First();