I am a developer at Microsoft and work in the .NET Common Language Runtime (CLR) team. For the last 4 years I have been working on virtual machine technologies on a variety of form factors including desktops (Windows, Linux), tablets (Win8), gaming-consoles (Xbox 360), mobile devices (Windows Phone 7, Windows CE, Symbian).I have worked on various core pieces of the runtime including Garbage Collector, memory manager, platform abstraction layer, runtime-performance, etc.Before working on .NET I worked on Visual Studio Team Foundation Server, Visual Studio Team System, Adobe Framemaker, Adobe Acrobat, Texas Instrument's Code Composer Studio.
One of the most common issues everyone is running into with Team Build is configuring the Drop Location.
All builds that happen through Team Build are dropped (bits are copied) to this location. Drop location is entered in the Location page of the Build Type wizard. This is essentially a shared folder on the network and needs to be available in UNC format as in \\server\share. However most users enter a path in the wizard and then any of the following three things happen
1. They forget to share the folder outResult: First build fails
2. The folder is shared out but adequate permissions are not given on itResult: First build fails
3. The folder gets unshared at some point of timeResult: Suddenly builds start failing after that
A common question is raised that both the first and second reasons of failure are a pre-requisite to starting a build, why doesn’t the Build Type wizard verify that the share exists. We could have done this but there are a couple of reasons we do not.
Firstly it could be a common scenario that the administrator is first setting up couple of Build Types and will then go and share those folders. So failing would simply hinder this process. However, this is not a very good excuse because we could have at least gone ahead verified the share and then given warnings stating that the share does not exist and the admin should share them with the correct permissions.
The main reason for not doing this verification is that scenario 2 is not easily verifiable. To undertand this let’s consider the permission required on the shared folder
1. The service account under which the Team Build Service is running on the Build Machine needs write permission on this folder
2. Other users need to have read permission on this folder so that they get to see build logs and the build itself
On the client where the Build Type is getting created through the wizard there is no information regarding the service account on the Build Machine so we cannot verify 1. This is because the admin while installing the BM could have chosen any valid account to run the service and can give explicitly and exclusive write permission to this account on the share. Moreover, user can change the Build Machine while firing the build and the service account on the new Build Machine might be a different account and that might not have permissions.
On OS’s like WinXP in addition to the sharing permission you can go to the security tab on the folders properties and apply a lot of permissions which are not accessible over the network but would make the build to fail. Take for example in share tab you give Full control to everyone and in the security for that folder you explicitly deny create folder permission. So even though our verification succeeds build will fail.
Verifying 2 does not add any value if we cannot verify 1.
Its not that we cannot verify drop location, what I tried to highlight above is that it is non-trivial. Many users think that the Wizard should just try to see if the share exists and then create and delete a file on the share to ensure it is writable. However for the reasons mentioned above this approach would just not work.
In one of the internal aliases there was a discussion going on some time back regarding which is the better way to unsubscribe from an event and why does the first one even work
In the first approach different objects are used to add and remove the event subscription. This can work only if the removal mechanism does not work by just comparing references. Because if it did then the removal mechanism would not find the object in the methods invocation list of the underlying delegate and would simply not remove the method.
I thought I’d do a little more snooping into this.
A class definition like public delegate void EventHandler(Object source, EventArgs eventArgs);
class MyClass
{
public event EventHandler MyEvent;
}
Is converted to code equivalent to
private EventHandler __MyEvent;
public event EventHandler MyEvent
add
lock (this) { __MyEvent += value; }
remove
lock (this) { __MyEvent -= value; }
So the compiler generates the add/remove accessors.
If you see the code of the accessors in ILDasm then you can see for the add_MyEvent method compiler emits code to call the System.Delegate.Combine method to combine the existing delegate and new delegate and for remove_MyEvent it uses System.Delegate.Remove method.
So
myClass1.MyEvent += new EventHandler(Function); è System.Delegate.Combine (myClass1.__MyEvent, newdelegate)
and
myClass1.MyEvent -= new EventHandler(Function); è System.Delegate.Remove (myClass1, newdelegate)
So all of the trick lies in the Combine and Remove methods of System.Delegate.
System.Delegate.Remove goes through the invocation list of the first delegate looking for invocations from the second delegate. If there is a match it removes it. System.Delegate overrides the == (Equals) operator so that the match does not happen based on object reference but based on the method the delegate encapsulates. This operator compares the instance object (null in case of static method callback) and the function pointed to and then removes the callback from the invocation list.
So both works but which one should we use? If the events are subscribed/unsubscribed once at the beginning/end like in a typical WinForm application then it hardly matters. However if this is done multiple times then the second approach is preferable as it does less of costly heap allocations and will work faster.
The complete code listing of the sample I used is as follows
using System;
using System.Collections.Generic;
using System.Text;
namespace EventAddRemove
public delegate void EventHandler(Object source, EventArgs eventArgs);
public void OnEvent()
if (MyEvent != null)
MyEvent(this, EventArgs.Empty);
else
Console.WriteLine("No Event to fire");
class Program
static void Function(object source, EventArgs eventArgs)
Console.WriteLine("Event got fired");
static void Main(string[] args)
Console.WriteLine("myClass1");
MyClass myClass1 = new MyClass();
myClass1.MyEvent += new EventHandler(Function);
myClass1.OnEvent();
myClass1.MyEvent -= new EventHandler(Function);
Console.WriteLine("myClass2");
EventHandler eventHandler = new EventHandler(Function);
MyClass myClass2 = new MyClass();
myClass2.MyEvent += eventHandler;
myClass2.OnEvent();
myClass2.MyEvent -= eventHandler;
Output is
myClass1
Event got fired
No Event to fire
myClass2
Lines in bold indicate that the correct methods was indeed removed from the invocation list in both approaches.
Just saw the post Slaves to email on excess email in MS and I couldn't agree more.....
Large email volume for people who manage others, or those who interact with external customers is expected. But even for individual contributors (Dev/Test) the volume is just too high. We should really use the internal communicator more and get rid of those one-liner emails.
Since we work in a different time zone within a team distributed between Redmond/NorthCarolina/India we face a different issue. Each morning you enter office and you are welcomed with 100s of emails which were sent to you in the local night time. By the time you wade through them almost an hour is over. Mondays are worse as you have to wade through the all the emails sent during Friday in US.
CLR took a DCR some time back on how nullable types are implemented. See here and here to find out more about the DCR. I found from one of the internal DLs that the fix was already in the RTM bits.
I wrote a small piece of code which should work only with the DCR changes and kept it aside so once this DCR gets implemented I'd try it out. So each time I upgraded to a new build of VS/CLR I built/ran this code to see if it works. And it just did, with my todays upgrade to about 10 day old build in our lab. The new nullable type after becoming a basic runtime intrinsic just rocks. I have put in comment all the failures that used to happen previously with the same piece of code....
// this code works only with the latest bits of // Visual Studio 2005 (C#2.0) and will fail to // compile/run with older Beta2 bits
// this always worked if (nullval == null) Console.WriteLine("It worked"); // this used to fail before and I think one of // the biggest issue with the previous implementation object nullobj = nullval; if(nullobj == null) Console.WriteLine("It worked");
// previously required // box = Nullable.ToObject<int>(val); argh!!!! object box = val;
// If you do not need exceptional code // (that's code that throws exception) // you needed to do int? unbox = Nullable.FromObject<int>(box); int? unbox = (int?)box; if (unbox == val) Console.WriteLine("It worked again");
int intval = (int)box; if (intval == val.Value) Console.WriteLine("attained Nullable Nirvana");
int x = 10; object y = x; // Previously Exception!!! cast is not valid int? z = (int?)y;
IComparable c = val; // Previously Exception!!! : object type cannot be // converted to target type if(c.CompareTo(box) == 0) Console.WriteLine("I have seen it all");
// compilation failure IComparable<int> ic = val; if(ic.CompareTo((int)box) == 0) Console.WriteLine("Wow there is even more to see");}
The output of the program is
It workedIt workedIt worked againattained Nullable NirvanaI have seen it allWow there is even more to see
Sometimes we get so used to things being the way they are we stop questioning them. We always have the perception in mind that individual frames of animated logo in a Bitmap strip is always horizontally arranged. I remember writing code to extract icons from a image lists that store individual frames of an animation sequence one after the other horizontally using something like
animationIcons = new Icon[bitmapStrip.Width / 16];for (int i = 0; i < m_animationIcons.Length; i++){ Rectangle rect = new Rectangle(i*16, 0, 16, 16); Bitmap bmp = bitmapStrip.Clone(rect, bitmapStrip.PixelFormat); animationIcons[i] = Icon.FromHandle(bmp.GetHicon());}
Even winforms ImageList works on this assumption that the AddStrip method of the ImageCollection in the control has the images placed side-by-side. However this is not at all the optimal placement of images. Read it on Raymond Chen's blog .....
I saw from Soma's blog that VS is taking a DCR to fix the issues about Nullable types that is being talked about in various blog. This is super cool as Microsoft demonstrated like never before that we do care about customer feedback as this is a direct result of some solid feedbacks. If you do not get the connection read Cyrus Najmabadi blog pointing to one of the original blogs that brought out the issue http://sab39.dev.netreach.com/Blog/12?vobId=172&pm=18
Some of us were just chatting about my previous post about function generators and we wondered about whether it can be done in C++ without using function pointers.... Most of my C++ knowledge has been rusted beyond repair but I thought even though its not possible to do directly, one can overload the ( ) operator to simulate this. So it should be possible to code so that the following is valid
FuncGen(Adder)(p1, p2)
Here the part in red semantically behaves like a function generator returning different functions based on the flag you pass. So here's some code in C++ that does it. Again I want to stress that this is not a function generator in C++, it just simulates something like it so that a statement like FuncGen(Adder)(p1, p2) will actually work....
#include
enum
class
private
CFunc cfunc;CFunc& FuncGen(FuncType ftype){ cfunc.m_funcType = ftype; return cfunc;};
int
Instead of using a global variable like cfunc I could have also created a object on the heap in FuncGen and later deleted it but since I have been coding in C# so long that I felt too lazy to write a delete statement.
The blogs are buzzing with continuation support in C# 2.0 and what cool things can be done with it. http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons explains the concept of continuation extremely well. I also found Don Box's posting http://pluralsight.com/blogs/dbox/archive/2005/04/27/7780.aspx very interesting.
Traditionally in languages like C/C++ functions works off the stack. Each function call creates a new frame on the stack in which current context is stored (return address, current stack pointer) and then any arguments to the function is pushed in. The function also creates all its local variables on the stack and pops them off before the function returns. So when the function returns, all information regarding the functions execution is lost. So in case you call the function again it starts from the beginning.
However in continuation this is not what happens. Here the state of the function is preserved and when you call back on the function it starts off from where it left off. All the function locals are allocated on the heap so that their values are preserved when the function is called again. In C# we have a *very* restricted version of continuation using the yield return statement. Even though its restrictive it allows some very cool way of programming.
Here a sample of code where I have a container containing my friends names and I enumerate them.
public class MyContainer { string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" }; public IEnumerator<string> GetEnumerator() { for (int index = 0; index < m_friends.Length; index++ ) yield return m_friends[index]; }}
class Program{ static void Main(string[] args) { MyContainer myContainer = new MyContainer(); foreach (string str in myContainer) Console.WriteLine(str); }}
You can have multiple enumerators too as in
public class CoolContainer { string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" }; public IEnumerable<string> straight { get { for (int index = 0; index < m_friends.Length; index++ ) yield return m_friends[index]; } } public IEnumerable<string> Reverse { get{ for (int index = m_friends.Length - 1; index >= 0; index--) yield return m_friends[index]; } }}
class Program{ static void Main(string[] args) { CoolContainer cc = new CoolContainer(); foreach (string str in cc.Reverse) Console.WriteLine(str); Console.WriteLine("----------------"); foreach (string str in cc.straight) Console.WriteLine(str); }}
Seeing all these work I got carried away and tried to do the enumeration without the foreach as in
IEnumerator<string> enumerator = myContainer.GetEnumerator();
enumerator.MoveNext();
Console.WriteLine(enumerator.Current);
enumerator.Reset();
My idea was that after the call to Reset internally I would be able to reach the first element in the list as the index variable will be reset. That’s where I got the surprise in the form of a NotSupportedException in the call to Reset. I send emails to the CSharp user group and found out that its indeed not supported and you need to create new enumerator to go back or if the enumerator once runs till end (i.e. one return is executed) then you’ll automatically get the reset you wanted. This means that iterating twice or more using the same iterator works as in
MyContainer myContainer = new MyContainer();foreach (string str in myContainer) Console.WriteLine(str);foreach (string str in myContainer)
Console.WriteLine(str);
< this tool has been updated check out here>
As we go on developing the product we frequently feel strong about doing new things around our product either to increase customer value, easy of use, flexibility or just because it can be done. Most of these are either too late to be included in the product or does not meet the criteria. Either way they serve as great samples and keep us busy.
One great example would be RSS feed for Team Foundation version control checkin notifications. Check out http://blogs.msdn.com/jefflu/archive/2005/07/27/443900.aspx. So now in addition to getting emails, you can also subscribe for RSS feeds.
Similarly for Team Build I have written a tool that monitors Team Build events and shows notifications with link to the Web UI of the Build. Currently it has the following feature
I plan to add additional features like listing all builds on the server and allowing user to specify different user name to connect to the server (required if running from home PC).
Anonymous Method
One of the new features in C#2.0 being shipped in with Whidbey is anonymous methods. Though this at first glance looks like an easy way of creating delegates, where instead of having to create a new function which the delegate will call you can pass the code inline.Before C#2.0
With C#2.0 and anonymous methods: the Function is eliminated and the same piece of code can be written more elegantly as follows
class MyClass{ delegate void MyDelegate(); static void Main() { MyDelegate writeMessage = delegate () { Console.WriteLine("I'm called"); }; writeMessage(); }}
For more details on Anonymous methods check out http://msdn.microsoft.com/msdnmag/issues/04/05/c20/default.aspx.
However, there is more to it than just getting a short hand way of writing code. With anonymous methods you can now do a lot of things in C# which are commonly done in Functional languages. Consider the code below which is actually a function generator.
static void Main(string[] args) { MyDelegate<int> mdWith = FunctionGenerator<int>(FunctionType.WithPrefix); mdWith(5); mdWith(5); MyDelegate<string> mdWithout = FunctionGenerator<string>(FunctionType.WithoutPrefix); mdWithout("Hello"); }}
The output is 0 : 51 : 5Hello
As in the above piece of code you can create Function Generator that actually return different implementations based on requirement. For another interesting sample see Don Box's blog http://pluralsight.com/blogs/dbox/archive/2005/04/17/7467.aspx
Closure
For any languages which allow passing around functions as arguments or functions returning another function the Closure abstraction is very important. For more info on Closure see http://en.wikipedia.org/wiki/Closure_(computer_science). C#2.0 supports closure by the use of anonymous methods.
Closure is a function along with its lexical environment (available variables and their values) when the function is created.
int i = 10; return delegate(T t){ Console.WriteLine(i.ToString() + ": " + t.ToString());};
Since the variable i was available with the value 0 when the Anonymous method was created, inside the method, i will be available with the same value when the method is called via the delegate.
From the definition of Closure it can be inferred that Closure remembers the values of the variables during its creation. However in C# the outer local variable (i in this case) is shared with the anonymous method by creating it on the heap. This means any change to it in the anonymous method changes the original value and when the method is called the second time it gets the modified value of i as 1 (see second line of output). This leads many to argue that anonymous method is not actually a Closure as by its definition the value of a variable at the time of creation of the Closure should be remembered and not modifiable.
Check out the link http://blogs.msdn.com/brada/archive/2004/08/03/207164.aspx on how the implementation of Anonymous methods in C# have led to interesting issues.