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();

Friday, August 19, 2011

Not so static

Today I've caught curious exception in the code like below:

class Drawer
{
    private static readonly Pen = new Pen(Color.White) { Width = 5 };

    public Bitmap DrawEllipse(int width, int height)
    {
       var bitmap = new Bitmap(width, height);
       using (var graphics = Graphics.FromImage(bitmap))
       {
         graphics.DrawEllipse(Pen, 0,0, width, height);
       }
       return bitmap;
    } 
}

Just an "optimization" not to create a pen every time and keep it static for "caching".

Friday, August 12, 2011

Is it C#?

Some weird but pretty code trick.

It is c#?
var hash = new Hash
                  {
                   a => "A value", 
                   b => "B value"
                  };
Console.WriteLine(hash["a"]);

Friday, July 15, 2011

Trace the stack

There are two ways to get current stack trace:

1. Using System.Diagnostics.StackTrace:
var stackTrace = new StackTrace(true);
foreach (var r in stackTrace.GetFrames())
{
       Console.WriteLine("Filename: {0} Method: {1} Line: {2} Column: {3}  ",
           r.GetFileName(),r.GetMethod(), r.GetFileLineNumber(),
           r.GetFileColumnNumber() );
}

2. Using System.Environment:

Console.WriteLine(Environment.StackTrace);

Wednesday, June 29, 2011

Coconut

Simple, but little painful snare regarding Streams and StreamWriters.

Let's imagine we have a function that print some data to a TextWriter:

void Print(TextWriter writer)
{
 // ...
}

Also we have a stream (e.g. Http output stream), which we want to use to print in data. So, we'll write something like:

using (Stream stream = GetOutputStream()){
  var streamWriter = new StreamWriter(stream);
  Print(streamWriter);
}

This code is fair enough - as far as StreamWriter uses the disposed stream, there should not be any resource leaks as far as we're disposing the thread. But there is some bug which can lead to data losses.

Monday, April 11, 2011

Ex-tension

There is a simple rule of thumb in which namespace extensions methods should be put. If this is a general purpose extension method - put it in the same namespace as 'this' parameter:

namespace System
{
 public static class StringExtensions
 {
  public static string Fmt(this string format, params object[] args)
  {
   return string.Format(format, args);
  }
 }
}

If an extension method use some specific parameters, but still is more or less general purpose, put in into the narrowest namespace of method parameters.

And if the method is specific method, put it in the namespace where it will be used. Also it is good to mark this method as 'internal'.

Wednesday, April 6, 2011

Common LINQ mistakes

  1. Never use
    enumerable.Count() > 0

    Instead use
    enumerable.Any()

    Count() will enumerate entire collection, Any() will stop after first item.
  2. Never ever use
    from x in enumerable
    orderby x.Item1
    orderby x.Item2
    select x;
    
    Your collection will be ordered by x.Item2, not by x.Item1 then by x.Item2. Instead use:
    from x in enumerable
    orderby x.Item1, x.Item2
    select x;
    
    The same is applicable for extensions methods.
    Wrong:
    var ordered = enumerable.OrderBy(x=>x.Item1).OrderBy(x=>x.Item2);
    
    Correct:
    var ordered = enumerable.OrderBy(x=>x.Item1).ThenBy(x=>x.Item2);
    
  3. Do not forget about closures scope.
    foreach (var x in enumerable)
    {
     var some = enumerable2.Where(y => y == x);
     list.Add(some);
    }
    
    As far as x is closed, you probably assume that 'some' will depend on each item from 'enumerable'. But actually, 'x' is defined outside of foreach (due to C# implementation), so all 'some's will be calculated using the last value. To prevent this, either fold all enumerables (in general - all lazy calculations) inside blocks, or use locally scoped variables.
    foreach (var x in enumerable)
    {
     var local = x; 
     var some = enumerable2.Where(y => y == local);
     list.Add(some);
    }
    
    Fortunately, Resharper will not let you forget about this.

Monday, January 17, 2011

How to create generic type

Just a side note.

If you need to create a generic type having only Type object of the generic argument, you could do this (e.g. we need to create List of some objects):

public IEnumerable CreateList(Type elementType, int capacity)
{
    Type listType = typeof(List<>).CreateGenericType(elementType);
    return (IEnumerable)Activator.CreateInstance(listType, capacity);
}

Note, that you cannot return List<T> because you do not actually have compile-time type List<T>. So you need to cast the result of Activator.CreateInstance to some non-generic type.