I know the answer (it's 42)

A blog on coding, .NET, .NET Compact Framework and life in general....

Posts
  • I know the answer (it's 42)

    Cool new C# syntactic sugar

    • 10 Comments

    Just the other day I ranted about all the explicit get; set; implementation and I found this out today.

    I was reviewing some code and I saw something like this

    class MyClass
    {
        public int Property {
            get; set;
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            mc.Property = 42;
            Console.WriteLine(mc.Property);
        }
    }

    I was completely confused. How the hell is there a abstract property in a concrete class? Then I figured out that this is new short-hand supported by Visual Studio 2008 (code-named Orcas and you can check this out in the latest beta).

    The compiler generates the field for the property and also generates the code in the get set to point to the field.

    internal class MyClass
    {
        // Fields
        [CompilerGenerated]
        private int <Property>k__BackingField;
    
        // Properties
        public int Property
        {
            [CompilerGenerated]
            get
            {
                return this.<Property>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.<Property>k__BackingField = value;
            }
        }
    }
  • I know the answer (it's 42)

    Coding conventions

    • 13 Comments

    <rant>

    Most of the coding convention I've seen being used by SW houses seems to promote wastage of lines. I suspect that since in many cases code size is measured in LOC it actually helps quoting a larger number. E.g. I start getting a tad irritated when I have to write code as follows

    // Why do I have to put in the enclosing curly braces :(
    if(flag)
    {
       Func();
    }
    // Can't I just use get { return foo; } and set {foo = value; }
    public CFoo Foo { get { return foo; } set { foo = value; } }
    </rant>
  • I know the answer (it's 42)

    Geek talk - Soul searching

    • 1 Comments

    Capture

  • I know the answer (it's 42)

    Sharing enums across C# and C++

    • 7 Comments

    On an internal DL someone asked a question about how folks share enums between C++ and C# code when required (e.g. common error codes for a large project that use both native code and C#).

    There was a very interesting answer given by one person. He simply asked why don't you define it in a .cs file and #include that file in your C++ code. I initially thought what the hell is he talking about and then it struck me that C++ and C# is not just similar but in some context they are exactly the same. Consider the following enum definition in a .cs files

    // File Enum.cs
    namespace
    EnumShare { enum MyEnum { a = 1, b = 2, c = 3, }; }

    This can be simply included in a C# project to be built normally. However, it can also be pulled into C++ code as follows

    #include "..\EnumShare\Enum.cs"
    
    using namespace EnumShare;
    
    int Foo()
    { cout << a << endl;

    }

    Note that I could directly pull in the C# code because the syntax matches that of C++ :)

    I thought that this was a rather interesting usage.

  • I know the answer (it's 42)

    Interesting Linked-List problem

    • 20 Comments

    Here's another problem which was given to me by Amit. I had lots of fun solving this :) 

    image

    Consider two link list as shown above which are joined at some point. The problem statement is as follows

    "Given pointers to two single-linked list, find out if they are joined and at which node they are joined. Use constant space to solve this and assume that the nodes cannot be modified."

    From the experience of the previous similar problem I posted let me first explain what is meant by constant space . Constant space means that the algorithm should use constant amount of space and its memory allocation should NOT increase as the length of the list increases. This means ironing out every byte allocation is a NOT a goal (constant space doesn't mean least amount of space). Just ensure that the allocation doesn't increase with the length.

    Non-Solution 

    The above two constrains rules out the two most common brute force algorithms that come to mind

    1. Add another bool/bit field to the nodes and while traversing the list mark the node by setting this field. Check out while traveling in second pass through the other pointer whether any node has this field set which would give the common node. There are some possible optimization over this like traversing the two lists in parallel so that not all the nodes be touched in the first pass.
    2. Create list/hash-tables of the nodes for look up later

    My-Solution

    I call this my solution because I'm sure there are better solutions to this :). This is O(n) solution.

    The pseudo-code

    1. Traverse the first list looking for the last node and compute the list's length (say len1)
    2. Traverse the second list looking for the last node and compute it's length (say len2)
    3. The last nodes of the two list has to be the same if they have joined anywhere in the middle. If not then the lists are not joined and hence return NULL
    4. Find whichever is the longer list (using len1 and len2) and increment the root pointer of that list by abs(len1 - len2). This would ensure that both the pointers are equidistant from joined node.
    5. Make another pass through the list by incrementing both the pointers and at every step ensure if they point to the same node. Since both are equidistant from the joined node (see step 4) this check will succeed and return the joined node.

    The C++ code looks something as follows

    // Data-structure for the node
    typedef
    struct Node { Node(int pVal) { val = pVal; p = NULL; } int val; Node *p; } *PNODE; PNODE GetJoinedNode(PNODE LL1, PNODE LL2) { // handle null lists if(LL1 == NULL || LL2 == NULL) return NULL; PNODE t1 = LL1, t2 = LL2; int len1 = 1, len2 = 1; // Find first list's length and it's last node for(;t1->p != NULL; t1 = t1->p) ++len1; // find second list's length and it's last node for(;t2->p != NULL; t2 = t2->p) ++len2; // last node not same means no joins in the middle if (t1 != t2) return NULL; // Advance the longer list by the difference in length so that // the pointers are equidistant from the join PNODE* t = len1 > len2 ? &LL1 : &LL2; AdvanceBy(t, abs(len1 - len2)); // last pass to find the join. for(;LL1 != LL2; LL1 = LL1->p, LL2 = LL2->p); return LL1; } void AdvanceBy(PNODE *pNode, int val) { for(int i = 0; i < val; ++i) (*pNode) = (*pNode)->p; }
  • I know the answer (it's 42)

    Dark UI Background

    • 1 Comments

    I have always been a fan of dark UI-backgrounds, especially for code-editors. I used dark schemes like darkblue for gvim and custom dark color-scheme for VisualStudio. I always thought they are good for the eyes (less radiation) and saves power.

    Looks like I'm no longer right in the days of LCD displays. Check out the details here. However, I did like the idea of http://www.blackle.com/.

  • I know the answer (it's 42)

    First Rosario CTP is out

    • 2 Comments

    If you follow other VSTS blogs, I'm sure you are already aware of the first ever CTP of Microsoft® Visual Studio® Team System code name “Rosario”. For me this is extra cool because this is the first VSTS CTP on which I've worked. As I had mentioned earlier I moved into VSTS team from my earlier TFS (Team Foundation Server) team over a year ago.

    We have been working on a lot of cool stuff and you can see the first sneak preview in this CTP. You can download the VPC from here and learn more about it from the whitepaper here. You can also check out the overview of the release in Jeff Beehhler's blog.

  • I know the answer (it's 42)

    Reverse string

    • 20 Comments

    A friend of mine forwarded me this nice little problem he got asked in some interview.

    Write code to reverse a string such that the words are reversed as in "We apologise for the inconvenience" becomes "inconvenience the for apologise We".

    Obviously (is there fun otherwise?) the problem had to be solved for a memory constraint device (constant space).

    I thought I'd share the solution as its kind of neat.

    The solution is to do it in two passes. In the first pass the whole string is reversed and in the second each word is reversed again.

    After reversing the whole string: "ecneinevnocni eht rof esigolopa eW"
    Reversing word at a time:           "inconvenience eht rof esigolopa eW"
    ...
    Finally:                                         "inconvenience the for apologise We"

    A simple version of code (non-Unicode and considering only space as an word separator) doing this is as follows

     

    // reverses text in between two pointers
    void
    Reverse(char *c1, char *c2) { while(c1 < c2) { char ch = *c1; *c1++ = *c2; *c2-- = ch; } }


    // reverses the complete string void Reverse(char *str) { if (!str) return; printf("'%s' ===> ", str);
    if(strlen(str) > 0) {
    // get the complete string reversed in pass 1 Reverse(str, str + strlen(str) - 1); char *c1 = str, *c2 = str + 1; do {
    // find word boundary for(;*c2 != ' ' && *c2; c2++);
    // reverse each word
    Reverse(c1, c2 - 1); if (!*c2) break; // reached end of string c1 = ++c2; }while(*c2); } printf("'%s'\n", str); return; }
  • I know the answer (it's 42)

    Tail recursion on .NET

    • 4 Comments

    What's tail recursion

    If you know its nothing to do with any of your pet's tail then get onto the next section.

    Tail recursion is a special case of recursion where the last call in a method is a recursive call.

    The major issue with recursion is that with each recursive call the stack grows by the stack frame allocated to the function call and soon it hits a stack overflow in case the recursion is too deep. Consider the following code which recursively counts down from a given number. In case you call this method with 100000 or some such large number it'll crash on your face with a StackOverFlow exception.

    static void CountDown(int num)
    {
        Console.WriteLine("{0} ", num);
        if (num > 0)
            CountDown(--num);
    }

    Optimizing tail recursion

    Interestingly the above code is of the special tail-recursion form. Since the last call is the recursive call there is no need to preserve stack frame of the calling function and the compiler can easily use this information to generate machine instruction such that the stack doesn't grow at all.

    In C# terms the above code can be optimized by the compiler into something like

    static void CountDown(int num)
    {
    START:
        Console.WriteLine("{0} ", num);
        if (num > 0)
        {
            --num;
            goto START;
        }
    }

    In this code the parameter is replaced on the same stack and the execution is simply short-circuited to re-start on that.

    All of this is fine but does .NET support this

    Instead of a straight answer lets try to see ourselves. I'll first comment out the Console.WriteLine code in the first method to make it simply, build it and disassemble it using the trick mentioned in my previous post. The generated IL for this method looks something as follows

    .method private hidebysig static void  CountDown(int32 num) cil managed
      {
        // Code size       25 (0x19)
        .maxstack  2
        .locals init (bool V_0)
        IL_0000:  nop
        IL_0001:  ldarg.0
        IL_0002:  ldc.i4.0
        IL_0003:  cgt
        IL_0005:  ldc.i4.0
        IL_0006:  ceq
        IL_0008:  stloc.0
        IL_0009:  ldloc.0
        IL_000a:  brtrue.s   IL_0018
    
        IL_000c:  ldarg.0
        IL_000d:  ldc.i4.1
        IL_000e:  sub
        IL_000f:  dup
        IL_0010:  starg.s    num
        IL_0012:  call       void TailRecursion.Program::CountDown(int32)
        IL_0017:  nop
        IL_0018:  ret
      } // end of method Program::CountDown
    
    

    From the IL marked with red its evident that the C# compiler at-least doesn't do this optimization and emits a normal recursive call.

    However, .NET platform needs to support all sorts of languages including those like scheme where the only way to do iteration is to convert the code into tail-recursion and the compiler is supposed to do the above mentioned optimization.

    It's exactly for this reason there is a supported IL instruction named tail. Using this I can modify the above code to as follows.

    .method private hidebysig static void  CountDown(int32 num) cil managed
      {
        // Code size       25 (0x19)
        .maxstack  2
        .locals init (bool V_0)
        IL_0000:  nop
        IL_0001:  ldarg.0
        IL_0002:  ldc.i4.0
        IL_0003:  cgt
        IL_0005:  ldc.i4.0
        IL_0006:  ceq
        IL_0008:  stloc.0
        IL_0009:  ldloc.0
        IL_000a:  brtrue.s   IL_0029
    
        IL_000c:  ldarg.0
        IL_000d:  ldc.i4.1
        IL_000e:  sub
                  tail.
        IL_0023:  call       void TailRecursion.Program::CountDown(int32)
        IL_0029:  ret
      } // end of method Program::CountDown
    
    

    From CIL ECMA 335 spec "use a tail. prefix to specify that the current stack frame should be released before transferring control. If the call would transfer control to a method of higher trust than the original method the stack frame will not be released."

    This single instruction is very significant in this context. So now if I assemble this using ilasm and run it with as big a number I fancy it'll not crash (obviously it may take hours to compute though).

    Update: Through our internal C# DL I got to the gory details. Check out the links here and here

  • I know the answer (it's 42)

    Easy way to modify IL code

    • 3 Comments

    Sometimes I try to write a little bit of IL code or modify bits and pieces here and there (specially modify IL generated from say C# code).

    The problem is writing up the complete IL that compiles into an exe is a pain (specially because my usage is to tweak them). To work around this I use the following flow which I thought I'd share

    1. Write C# code that meets the need
    2. Build it
    3. Disassemble the exe by using the following command
      ildasm /out=file.il My.exe 
    4. Tweak the IL inside the file.il file
    5. Assemble it back again with
      ilasm file.il

    the neat part is the /out parameter which makes ildasm dump a single IL for the entire code. At the beginning I used to try patching the code up by copy-pasting from ILDASM UI which show separate IL code for every method :(

  • I know the answer (it's 42)

    Type cast to generic type

    • 6 Comments

     

    The following question got posted to one of the internal DLs.

    Why does the following fail to compile.

    public interface A { }
    public class B : A { }
    public class C : B { }
    
    class D
    {
        public void f()
        {
            C c = new B() as C; // Valid!
        }
    
        public void g<T>() where T : A
        {
            T t = new B() as T; // Invalid! Error CS0413
        }
    }

    The constraint (where T : A) clearly tells the compiler that T is A and B derives from A. So it should've been possible to cast B into T. However, the compiler fails with a "The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint".

    If the above was possible then I would've been able to do the following

    struct S1 : A { }
    D d = new D();
    d.g<S1>(); // meets the constraint that S1:A

    This means that effective we are doing  T t = new B() as S1. But the C# spec clearly calls out "In an operation of the form e as T, e must be an expression and T must be a reference type". This means that using a struct (value type) in an as statement is not allowed and would make the above illegal.

    The solution is to tell the compiler that I'd only send reference types for T and you do this by

    public void g<T>() where T : class, A
    {
        T t = new B() as T; // Invalid! Error CS0413
    }
  • I know the answer (it's 42)

    Difference in conversion of anonymous method and lambda expression

    • 4 Comments

    Consider the following class

    delegate void Moo(int a, int b, int c);
    
    class A
    {
        public event Moo moo;
    }

    In case I want to create a handler for the moo event where I don't care about the 3 parameters needed by the event handler I can easily write it as

    A a = new A();
    a.moo += delegate { count++; };

    However, in case I want to create the same handler with a lambda expression. I have to do it as

    A a = new A();
    a.moo += (a1,a2,a3) => count++;

    There is no shortcut to this. I can't use say a.moo += () => count++;

    The reason lies in the fact that both support a different set of conversions.

    From C# 2.0 spec (§21.3 - Anonymous methods conversions)

    An implicit conversion (§6.1) exists from an anonymous-method-expression to any compatible delegate type. If D is a delegate type, and A is an anonymous-method-expression, then D is compatible with A if and only if the following two conditions are met.

    • First, the parameter types of D must be compatible with A:

    o If A does not contain an anonymous-method-signature, then D may have zero or more parameters of any type, as long as no parameter of D has the out parameter modifier.

    In C# 3.0 spec for Lambda expression conversion it sez

    Specifically, a delegate type D is compatible with a lambda-expression L provided:
    • D and L have the same number of parameters.
    • If L has an explicitly typed parameter list, each parameter in D has the same type and modifiers as the
    corresponding parameter in L.
    • If L has an implicitly typed parameter list, D has no ref or out parameters.
    ...

    In both the cases the lines marked in red indicate why one is different from the other.

  • I know the answer (it's 42)

    A classic Daily WTF find

    • 1 Comments

    If you visit the Indian Railway site and press any of Ctrl/Alt keys it pops a message "Sorry, you do not have permission to press the key". Hey, it's my keyboard and I have all the permission in the world to press whatever I want.

    This is exactly like one of those WTF finds.

  • I know the answer (it's 42)

    Bestsellers list tells a lot

    • 1 Comments

    Right now on Amazon the third most selling book is 21 Pounds in 21 Days: The Martha's Vineyard Diet Detox. This says a lot about developed countries :)

  • I know the answer (it's 42)

    Writing in reverse

    • 4 Comments

    As a kid, like most other kids I used to spend time learning to do weird things like write in reverse (as text seen in mirror-reflection), or write flipped text so that the person seeing the paper from the other side could read it.

    Today I hit upon http://www.revfad.com/flip.html which can flip any text you give it. Like this ɐqɐuıɥqɐ. What it does is for every English character it finds another Unicode character whose glyph looks like the flipped version of that character.

    I tried to demo my weird writing skills to Amit. This is what I got writing at about 0.25 times the normal writing speed.

    signature

    Now my IM message is going to say ǝǝɹɟ ɯ,ı.

  • I know the answer (it's 42)

    VSTS Source Control Annotation

    • 4 Comments

    One of the coolest feature of the upcoming Orcas release is the Source-Control file Annotation feature.

    "Annotate is a feature that allows developers to inspect a source code file and see at line-by-line level of detail who last changed each section of code. It brings together changeset data with difference technology to enable developers to quickly learn change history inside a source file.".

    This is the tool for you if you want to figure out a change by contacting a developer or want to play the "you screwed up" blame game. You can right click any source-controlled file in the solution explorer and choose annotate.

    This is how the file is annotated at line-level

    Capture

  • I know the answer (it's 42)

    Using Trace-Points in Visual Studio

    • 2 Comments

    Even though everyone knows about break-points, trace points seem to have been used way less.

    Developers sometimes need to inspect variables and other state as a program flows without interrupting the execution (so no break points). Even if the program is built with detailed tracing (as outlined here) a lot of things are missed in them (how  many local variables are traced?).

    So most developers quickly add a Console.WriteLine or Debug.Trace.Write to dump the information. Now this requires changing code (checkout), not able to remember all the changes and so forth.

    Visual studio supports this scenario very well. Just add a break point to the line where you want to trace and then right click on the break point icon and choose "When Hit" in the context menu. The dialog shown below opens up and you can choose to trace anything you want using the Print Message checkbox including function, thread, variables, messages. The messages are dumped to the output window when you debug the application. It's easy to manage these as well as they come up in the BreakPoints window (Debug->Windows->Breakpoints).

    Capture
  • I know the answer (it's 42)

    It's Link

    • 1 Comments

    I saw the same thing in TechMela which Dinesh reported. Many attendees was pronouncing LINQ as "link cue". The actual pronunciation is "link".

    Not that it matters much (this is not as bad as C Pound or C Hash where the meaning maybe completely lost).

  • I know the answer (it's 42)

    The difference between is and as and dealing with FxCop Warning CA1800: variable is cast multiple times

    • 7 Comments

    I had the following code

    public static void f1(object ob)
    {
        if (ob is Foo && ((Foo)ob).m == 10)
            Console.WriteLine("Yea");
    }

    This gave the following FxCop (Code analysis) performance warning: 'ob', a parameter, is cast to type 'ConsoleApplication5.Foo' multiple times in method 'Program.f1(Object):Void'. Cache the result of the 'as' operator or direct cast in order to eliminate the redundant castclass instruction.

    I could easily resolve this by using

    public static void f2(object ob)
    {
        Foo foo = ob as Foo;
        if (foo != null && foo.m == 10)
            Console.WriteLine("Yea");
    }

    Or in my scenario I could've ignored this warning as this code handles a very corner scenario where the is is supposed to fail almost 99.99% times and hence the cast bit would almost never be called (hence double cast would happen say 00.01% times).

    I had used the is subconsciously feeling that is is lighter weight than as . Even the as docs expresses as to be equivalent to expression is type ? (type)expression : (type)null;

    But if that was the case then there should've been no double cast warning (as is doesn't do a cast). So I did the obvious. Pulled up reflector on both these methods.

    The generated IL for f1 is as follows

    L_0002: isinst ConsoleApplication5.Foo
    L_0007: brfalse.s L_001d
    L_0009: ldarg.0 
    L_000a: castclass ConsoleApplication5.Foo
    L_000f: ldfld int32 ConsoleApplication5.Foo::m
    L_0014: ldc.i4.s 10
    L_0016: ceq 
    L_0018: ldc.i4.0 
    L_0019: ceq 
    L_001b: br.s L_001e
    L_001d: ldc.i4.1 
    L_001e: stloc.0 
    L_001f: ldloc.0 
    L_0020: brtrue.s L_002d
    L_0022: ldstr "Yea"
    L_0027: call void [mscorlib]System.Console::WriteLine(string)
    L_002c: nop 
    L_002d: ret 
    
    

    And that for f2 is

    L_0002: isinst ConsoleApplication5.Foo
    L_0007: stloc.0 
    L_0008: ldloc.0 
    L_0009: brfalse.s L_001a
    L_000b: ldloc.0 
    L_000c: ldfld int32 ConsoleApplication5.Foo::m
    L_0011: ldc.i4.s 10
    L_0013: ceq 
    L_0015: ldc.i4.0 
    L_0016: ceq 
    L_0018: br.s L_001b
    L_001a: ldc.i4.1 
    L_001b: stloc.1 
    L_001c: ldloc.1 
    L_001d: brtrue.s L_002a
    L_001f: ldstr "Yea"
    L_0024: call void [mscorlib]System.Console::WriteLine(string)
    L_0029: nop 
    L_002a: ret 
    
    

    So for both is and as the isinst IL instruction is used. One more interesting thing I noticed in the 2nd case is that after isinst there is no other casting IL used. Some more investigations revealed from this link that "The isinst instruction evaluates whether the reference on the stack is a Foo or a subclass of the Foo type. If it is, then the reference is cast to the type defined in the isinst instruction and pushed onto the stack. Otherwise the value null is pushed onto the stack."

    So this means that the documentation was over-simplifying the situation. is does the whole cast bit and the check is done by the brfalse.s L_001d  instruction which just checks the cast returned null or not. So in reality the equivalence is as follows

    is = (expression as type) != null;

  • I know the answer (it's 42)

    Which font do you use for your resume

    • 3 Comments

    I had asked this before, but this time the question is "which font do you use for your resume?". The other question is what do you tell a person who sent me her resume in Comic Sans MS font.

  • I know the answer (it's 42)

    Static method calls in generics

    • 1 Comments

    I go this question from a blog reader.

    "The following code should be possible

        public class Class1
        {
            public static void Hi()
            {
                Console.WriteLine("Hi");
            }
        }
    
        public class Class2<T> where T : Class1
        {
            public static void Hi()
            {
                T.Hi();//This should be possible.
            }
        }

    However, if you try to compile this then it fails with the "error: 'T' is a 'type parameter', which is not valid in the given context". At first to me it looked logical and symmetrical to be able to call static methods on a generic type by directly using the type parameter as during compile time it is known from the constrain that T is Class1 which has the static method Hi().

    Then I sent this to the internal C# DL to get this clarified. Eric Lippert gave the answer.

        public class Class3 : Class1
        {
            public new static void Hi()
            {
                Console.WriteLine("By");
            }
        }
    

    Since the user chose T.Hi() over Class1.Hi() it would mean that he expects a dynamic dispatch which lands in Class3.Hi(), but that is very misleading because by definition static methods are determined statically during compilation. So this option is pointless.

    If the call always lands in Class1.Hi() as in the case of true static call it should be, then the user would be better off having it as Class1.Hi() which is what is supported.

    Update: Just found that Eric has posted this on his blog. Check that out here

  • I know the answer (it's 42)

    The Microsoft Sourcer is here

    • 0 Comments

    I had never heard of this position before either , but in case you are looking for working with Microsoft anywhere in the world, Sourcer in Microsoft is your best bet. Check out Jim one of the sourcer here or see the cool video below


    Video: The Recruiters Lounge - Who is behind SourceCon?

  • I know the answer (it's 42)

    I'll be going to TechMela 2007

    • 1 Comments

    Like TechEd, here in India we are having TechMela this year. This time the venue is Mumbai and I'll be there!!!

    Unfortunately there is very little bit of Language stuff. I plan to attend all UX presentations (covered in the agenda's Track 2) and also attend our very own VSTS stuff presented by our PMs Abhishek Mathur and Rohit Chauhan.

    The  details of the VSTS presentations goes as follows

    1. Dev Oriented Testing using Microsoft Visual Studio Team System (with new "Orcas" Features) - Track 1
    2. Drill down into advanced features of Microsoft Visual Studio Team System - Track 2
  • I know the answer (it's 42)

    Interviewing with Microsoft India

    • 16 Comments

    "What to expect in the interview" I've had this question from candidates that I have referred or distant relatives or friend's friend (you get the idea!) who are appearing for an interview with Microsoft . Somehow people still get to hear that Microsoft asks riddles. Though this was true way back but now these questions are rarely asked as they indicate very little about the candidate's potential.

    I have been through interviews with some leading companies as an interviewer or interviewee and IMO Microsoft's interview process is a bit different. So here goes a list of what to expect and be prepared for in a technical interview with Microsoft.

    1. Unlike some other companies, Microsoft takes people from a lot of diverse background. E.g. if you are from C++ compiler development background you can be easily considered for the VS IDE's intelli-sense development if your interviewers think that you can fit in.
    2. Your dress really doesn't matter. You can expect to see your interviewer in shorts and he can't care less about what you wear.
    3. The interview process is loooooong. Expect multiple people to interview you one after the other. So when you get the lunch break, eat well.
    4. Put things in your resume only when you know about them well. People in Microsoft comes from diverse background (see above) and their  is every possibility that your interviewer will be very aware about the technologies you have mentioned in your resume and will ask you about them.
    5. Know your past projects well.
    6. You will be asked to solve technical problems and write pseudo-code for the solution. 
    7. Whether you are interviewing for Software development role, a test role or a lead/manager role you will be asked to code. The reason is simple, in Microsoft leads and development/test managers and even PUMs in some case (Program Unit Managers) code.
    8. Think aloud when solving problems, approach is as important as the final solution.
    9. When giving a solution, find out the fallacies your self and try to come up with better alternatives.
    10. Its an interview, so ask questions about Microsoft and the position/role you are being interviewed for.
    11. This is not true :)
  • I know the answer (it's 42)

    Adding Trace to a .NET application and listening to it

    • 12 Comments

    Just yesterday I was chatting with a friend and he was telling me how they are writing a thread-safe logging library for their .NET app. I was astonished to find out that they were completely unaware of the awesome trace library in .NET.

    So this post is about how to add configurable tracing to an .NET app and how to use some cool tools to see the log. In case you know about the how-to-add part skip down to the listening part as it talks about some neat tool you may not know about.

    Adding trace

    The System.Diagnostic namespace contains the tracing API's that are thread-safe, have configurable levels of tracing, zero-foot print with conditional compilation, trace listener support, etc...

    First lets define a simple wrapper class over the trace API

    public static class Logger
    {
        private static string procName =
                Process.GetCurrentProcess().ProcessName;

        private static TraceSwitch traceSwitch =
                new TraceSwitch("AppTraceLevel", null);



        [ConditionalAttribute("TRACE")]
        public static void Info(string format, params object[] args)
        {
            Info(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        [ConditionalAttribute("TRACE")]
        public static void Info(string message)
        {
            if(traceSwitch.TraceInfo)
                TraceLine(TraceLevel.Info, message);
        }

        [ConditionalAttribute("TRACE")]
        public static void Error(string format, params object[] args)
        {
            Error(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        [ConditionalAttribute("TRACE")]
        public static void Error(string message)
        {
            if (traceSwitch.TraceError) TraceLine(TraceLevel.Error, message);
        }

       
        // TODO: Add Warning/Verbose and other methods in line with Info/Error

        private static void TraceLine(TraceLevel level, string message)
        {
            string traceLevel = null;

            switch (level)
            {
                case TraceLevel.Error:
                    traceLevel = "ERROR:  "; break;

                case TraceLevel.Warning:
                    traceLevel = "WARNING:"; break;

                case TraceLevel.Info:
                    traceLevel = "INFO:   "; break;

                case TraceLevel.Verbose:
                    traceLevel = "VERBOSE:"; break;

                default:
                    traceLevel = "DEFAULT:"; break;
            }

            string finalMessage = string.Format(
                CultureInfo.InvariantCulture,
                "{0}, {1}, {2}, {3}, {4}", traceLevel, procName,
                Thread.CurrentThread.ManagedThreadId, DateTime.Now, message);
           
            Trace.WriteLine(finalMessage);
        }
    }

     

    The statement private static TraceSwitch traceSwitch = new TraceSwitch("AppTraceLevel", null); on the top is used to read the trace level from the Config file (more about how to use it below). After that the Log and the Error Methods simply forward the call to TraceLine. TraceLine creates a formatted message and uses Trace.WriteLine (message) to dump it to the Trace.

    The app just calls Logger.Info("message") or Logger.Error("message") to trace something.

    Note that the methods have conditional compilation attribute on it and hence have zero overhead in case the TRACE symbol is not defined.

    Configuring Trace and listening to it

    The trace-level and how the actual trace is dumped is configured using an App.Config file that is added to the application to be traced. The file after adding the configuration looks as

    <configuration>
      <system.diagnostics>
        <switches>
          <!--  0-off, 1-error, 2-warn, 3-info, 4-verbose. -->
          <add name="AppTraceLevel" value="4" />
        </switches>
    
        <trace autoflush="true" indentsize="4">
          <listeners>
            <add name="myListener"
                type="System.Diagnostics.TextWriterTraceListener"
                initializeData="C:\logs\TraceSample.csv" />
            <add name="EventLog"
               type="System.Diagnostics.EventLogTraceListener, 
                     System, Version=2.0.0.0, 
                     Culture=neutral, PublicKeyToken=b77a5c561934e089"
               initializeData="sample application"/>
          </listeners>
        </trace>
      </system.diagnostics>
    </configuration>
    

    Here we are setting AppTraceLevel to 4 which means that all tracing is allowed. If you set it to <=2 then calls from our Logger::Info will not be logged.

    We also have two different trace listeners configured. One is named myListener which uses the system provided file based tracing and dumps everything to a csv file (c:\logs\TraceSample.csv). We used a csv file because intentionally we chose a format of tracing (see string.Format in Logger::TraceLine) where the trace is comma separated and hence can be easily opened in Microsoft Excel. You can as well name it .txt and use notepad.

    The problem with file based tracing is that its not real-time and you can only post-process it. The other option is to see in real-time what is being traced. The 2nd trace option named EventLog just does that. It traces to the system event trace which you can see through the system management console in by running Start->Run->compmgmt.msc. However, a better tool for this job is DebugView  from the erstwhile Sysinternals now acquired by Microsoft. Its free and available from here.

    Install this and bring up DbgView.exe. Hit Ctrl+L to bring up the filters dialog (so that you can narrow down and only see your app's log). In the Include text box enter your application's name (note that we put that in the trace messages and hence you can filter on it).

    Run the App and DebugView will dynamically show the trace messages as the app traces them.

Page 7 of 16 (378 items) «56789»