DCSIMG
November 2007 - Posts - Doron's .NET Space

November 2007 - Posts

Restoring Shift+Tab in ReSharper

Since we installed ReSharper, we've noticed that the Shift+Tab shortcut has stopped working, which was a great annoyance to my team (ReSharper still rules, you ungrateful bastards). After some googling, the following forum post provided the solution:

  • Go to Visual Studio options -> Environment -> Keyboard.
  • Choose the action Edit.DecreaseLineIndent.
  • Change the scope to "Text Editor" (where it says "Global"), otherwise the following step won't work.
  • Hit Shift+Tab.
  • Assign.
  • You're good to go.

Hopefully JetBrains will get around to fixing this in the next version.

Posted by dorony | 3 comment(s)

C# 3.0 New Feature of the Week #3: Anonymous Types

This week's C# 3.0 New Features article will discuss a neat feature called anonymous types. You'll use it like this:

var me = new {Name = "Doron", Age = 24 };

The result is an anonymous type created behind the scenes, with two properties: Name and Age. We assign it to a local variable with the "var" keyword, since we can't really mention the type (because of all the anonymity). To know more about the var keyword, read my first article about C# 3.0. Since it is a full blown type, and not some kind of dictionary, you will have complete intellisense for the variable "me".

When should you use this feature? Well, probably not that often. It is mainly used for the sake of Linq, when you need to "select" a bunch of properties. Other uses might spring in the future like how the upcoming ASP.NET MVC framework will use anonymous types as dictionaries.

How is it implemented?

Reflector will show you this:

[CompilerGenerated, DebuggerDisplay(@"\{ Name = {Name}, Age = {Age} }", Type="<Anonymous Type>")] internal sealed class <>f__AnonymousType0<<Name>j__TPar, <Age>j__TPar> { // Fields [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly <Age>j__TPar <Age>i__Field; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly <Name>j__TPar <Name>i__Field; // Methods [DebuggerHidden] public <>f__AnonymousType0(<Name>j__TPar Name, <Age>j__TPar Age); [DebuggerHidden] public override bool Equals(object value); [DebuggerHidden] public override int GetHashCode(); [DebuggerHidden] public override string ToString(); // Properties public <Age>j__TPar Age { get; } public <Name>j__TPar Name { get; } }

Indeed, a new type was created for us, with the Name and Age properties. There are two things to pay attention to here. First, note that the class implements Equals and GetHashCode for us. Also note that the properties are not of type string and int, respectively. They are of type <Name>j__TPar and <Age>j__TPar, which are both generic arguments of the class.

Yep, our anonymous type is a generic one. Let's look at how it is instantiated.

<>f__AnonymousType0<string, int> type1 = new <>f__AnonymousType0<string, int>("Doron", 0x18);

Here we see that the compiler did infer that we are expecting a string and an integer, as these are specified as the generic arguments. Now that we know that, let's have a look at Equals:

[DebuggerHidden] public override bool Equals(object value) { var type = value as <>f__AnonymousType0<<Name>j__TPar, <Age>j__TPar>; return (((type != null) && EqualityComparer<<Name>j__TPar>.Default.Equals(this.<Name>i__Field, type.<Name>i__Field)) && EqualityComparer<<Age>j__TPar>.Default.Equals(this.<Age>i__Field, type.<Age>i__Field)); }

That's not the prettiest line of code, but we can see that the equality check is implemented by calling EqualityComparer<T>.Default. This in turn returns a default comparer for our anonymous type to use.

But why use a generic class in the first place? Why not just use the actual types? Wriju explains. It simply reduces the number of types that get created. If we had another variable that we assigned with the expression - new {Name="Doron", Age=23.5}, there won't be a need for another type in which Age is double. The same anonymous type will be used, with a different generic argument.

This concludes this week feature research. Since Visual Studio 2008 and .NET 3.5 are now officially released, that would be a great time for you to try them yourself. Shabat Shalom.

Posted by dorony | 5 comment(s)
תגים:,

A Geographic Nightmare

Oren Eini talks about nightmare platforms, and so I got the urge to talk about my issues with the GIS platform we are using - ESRI ArcGIS Server 9.2. First, let me state that this is a very powerful (and expansive) product. In fact, there is practically no other product that offers the features and capabilities you get with GIS Server. You can do practically anything geographic/mapping related with it. 

The product was built in a way so that by default, almost anyone can create maps and publish them in a web application or a web service. ArcGIS Server is great if all you want is to create maps with ArcMap (ESRI's desktop application that you use to, well, create maps), use Visual Studio to create a web-page from a template, and use that web-page to let clients view the map. Here is where the trouble begins for us developers. Thing is, if you want to create a real application, that is never enough.

The ArcGIS Server API for working with web applications, is called the Web ADF, and is composed from a host of server controls and libraries. I am sorry to say, that it is a horribly designed, badly documented piece of API. In other words, it sucks pretty bad. Now, I would be a bad sport if I didn't give a few example, won't I?

Let's start with the server controls. What ESRI wanted you to do is drag and drop some controls on a web-page and then go through some wizards to configure the controls. That would be things like, the server address to connect to, the name of the map to show, etc. Now, if you wanted to do something as simple as letting the user change the map he is currently viewing, that should be as easy as changing a property on the Map control, right?

Well, wrong. You have no idea how much trouble we had to go through in order to accomplish this simple task, only for our solution to be broken again upon installation of Service Pack 1 (by the way, the service pack count for ArcGIS 9.2 has already reached 4). We had to solve this issue by browsing reflector for the source code, and then try to find out exactly which code we have to run in each of the Map control life-cycle stages in order to get the damned thing to work. Unfortunately, the release version has its DLLs all obfuscated, so we actually had to go and install the Beta version on another PC, so we can reflect the DLLs whenever we encounter a non-solvable issue. How's that for a nightmare?

The drag-and-drop suckiness doesn't end here. There is a control, for example, that's called SearchAttributesTask. Now this control accepts a collection of layers and fields to search in (you type "bla" and you get to see all the buildings whose name contains "bla"). Now, guess what is the type of the property SearchFields for SearchAttributesTask? No, it's not a LayerFieldCollection, or something. It's a string. Yep, the control comes with a nice designer that serializes your choices to something like: SearchFields = "Buildings:::Name:::Size^^^Houses:::Area^^^...". In order to programmatically change the fields you want to search in, you would have to go and write your own code to create this string serialization, which we did.

The rest of the API is riddled with bad design choices and bugs. Weird exceptions get thrown. You find out that there are 5 different classes that are called Converter in this API, in 5 different namespaces, which in some situations can definitely be used together. Documentation for most methods is something like: Map.GetFunctionalities - "Returns the functionalities of the map." Oh really? Now I couldn't guess that on my own. I should mention that since the initial release the documentation has improved a lot, but it is still no paradise. Recent documentation for this method (added since Service Pack 2, if I am not mistaken), explains that it returns a collection of IMapFunctionality. So why, why oh why, does this method have a return value of IEnumerable? This is a .net 2.0 only library, for pit's sake, they can use generics. And they do, in many other places. Here, they don't. This kind of API inconsistency can drive a man insane, I tell you.

Now, you could decide to skip the ADF, and go right ahead and use the underlying ArcObjects - lower level COM objects that are pretty much the base of every ESRI software, including the Web ADF. Many things will require you to do this anyway, since only ArcObjects expose the full power of ArcGIS. Using ArcObjects feels a lot more consistent. It is terribly annoying to use, but at least in a consistent way. This is an API, as all COM API's, I venture, that relies on interfaces. A lot of interfaces. In fact, in order to accomplish a simple thing as adding a feature to a layer, you might have to get familiar with something like 8 different interfaces. Many times you are working with just the one object, which you have to cast as different interfaces in order to access specific methods (I believe the COM term for this is Query Interface).

Now COM is COM, can't really come complaining to ESRI, right? Well, watch me. For the amount of money an ArcGIS Server license costs, a .NET developer like me could very well expect a decent .NET API to work with. The Web ADF is a .NET API, but it is hardly as powerful as ArcObjects are, nor is it any kind of decent.

To conclude, I would say that ArcGIS Server 9.2 might be a great, easy to use product for some users. But if you're a developer that wants to create kick-ass, cutting-edge GIS stuff with it, you're in for a world of pain.

Posted by dorony | 12 comment(s)
תגים:

C# 3.0 New Feature for the Week #2: Object and Collection Initializers

Last week I started my series of posts about new C# 3.0 features, and my second post will be about object and collection initializers. I will also include a bonus - an easy way of having a collection initializer in C# 2.0.

Object Initializers

Say we have declared the following class (with the automatic properties syntax we learned about last week):

public class Person { public string FirstName {get; set;} public string LastName {get; set; } }

We can now initiate a Person in the following way:

Person p = new Person { FirstName = "Doron", LastName = "Yaacoby"};

Note that Person only has the default constructor, that accepts no parameters, and yet we have one line initialization for it. In C# 2.0 we have this ability as well, but only for attributes.

[System.AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] public sealed class CachedAttribute : OnMethodInvocationAspect

In the first example Person has to have a default constructor, since as we'll see, the compiler will convert our code to use it, and then set the properties. Of course that in that case, we could use one of the other constructors. It would look something like this.

Person p = new Person("Doron") {LastName = "Yaacoby" };

One might ask, why can't we always use a constructor? Well, a constructor doesn't usually include all properties - this allows for much more flexibility for object initialization. Also, it is a lot more readable than using a constructor, since the reader of the code can immediately see which properties we're initializing, instead of having to look at the constructor signature to understand. 

How is it implemented?

Lets have a look at the Reflector.

1 Person <>g__initLocal0 = new Person(); 2 <>g__initLocal0.FirstName = "Doron"; 3 <>g__initLocal0.LastName = "Yaacoby"; 4 Person p = <>g__initLocal0;

Again, rather obvious. The only question that comes to mind is, why bother creating a local variable and then setting our own variable to it? Why not just use "p" from the first moment? I'm guessing that the first 3 lines is the compiler's direct translation to "new Person{FirstName=...,LastName=...}". Say we're calling a method like this:

ToXml(new Person {FirstName = "Doron", LastName = "Yaacoby"});

Then in this case, the compiler would have to create a local variable in order to pass it to the method. When we were initializing "p", that variable was not required, but I guess the compiler doesn't bother to take a shortcut in this case.

Edit: Shani pointed me to a better explanation for this issue: having an atomic assignment. Thanks!

Collection Initializers

In a similar manner, we now have a shortcut for initializing collections.

List<string> names = new List<string> { "Team", "Fortress", "2"};

Rather like the way we could always initialize arrays, but now it works for any collection. Actually, it will work for any class that implements IEnumerable and has an appropriate Add method. We could also combine object initialization here:

Dictionary<int,Person> peopleDictionary = new Dictionary<int,Person> { {1, new Person { FirstName = "Doron"} } }

Here we initialized a dictionary of type int->Person. This dictionary implements IEnumerable and it has the method Add(int key, Person value). And so we initialize the dictionary with one key-value pair, that maps the integer 1 to the Person Doron.

How is it implemented?

Once again, let us reflect on our first example.

List<string> <>g__initLocal1 = new List<string>(); <>g__initLocal1.Add("Team"); <>g__initLocal1.Add("Fortress"); <>g__initLocal1.Add("2");

No surprises here. The compiler changes our code to creation of a list, and repeating calls to "Add". Although one thing to notice is that there's no use of the IEnumerable interface. So why is it required for usage of this syntax? For your code to make sense would be the logical answer. Consider the following code:

public class Calculator { public double Add (double x, double y) { return x + y; } } public void TestCalc() { Calculator c = new Calculator { 4, 2 }; }

Now if we didn't have the IEnumerable restriction this would actually compile, but would be absolutely meaningless.

Bonus: Collection Initializer with C# 2.0

We could simulate the behavior of a collection initializer by creating the following class.

public class ExtendedList<T>: List<T> { public ExtendedList(params T[] initalValues) { AddRange(initalValues); } }

Which can later be used this way:

ExtendedList<string> names = new ExtendedList<string>("Team", "Fortress" , "2");

Of course this is not as great as something that works with every IEnumerable, but I have found this to be quite useful, especially in unit-testing where you usually create test collections with a few parameters. You can download the complete class here.

Hope you enjoyed this. See you next week, with another new C# 3.0 feature.

Posted by dorony | with no comments
תגים:,

C# 3.0 New Feature for the Week #1: Automatic Properties

I've decided that I really need to get in the program and start learning C# 3.0 and Linq seriously. I've been planning to this for a long time, and even started playing with it a little, but never dug in really deep. So my new "C# 3.0 New Feature for the Week" series of posts is about getting myself to commit to studying and blogging about it. Every week I will present one new feature and talk about what is it good for and how it is implemented.

So here we go. The first feature we'll talk about is automatic properties. This is a cute little feature, meant to save us having to write this:

public class Person { private string _firstName; public string FirstName { get { return _firstName; } set { _firstName = value; } } private string _lastName; public string LastName { get { return _lastName; } set { _lastName = value; } } }

I mean, usually there's no logic inside the properties getters and setters, but since you like to write good and maintainable code, you use properties in case you'd like to add something in the future. But still, having to write a million of them can be quite a *** (well, at least if you don't have ReSharper. If you do, Alt+Insert is all you need).

So now what we can write is:

public class Person { public string FirstName {get; set;} public string LastName {get; set; } }

If we want, we can add access modifiers, like this:

public string FirstName {get; internal set;}

Isn't this so very nice and clean? If we now want to add something inside the getter or setter, we can convert it to a standard property (hopefully ReSharper 4 will have this much needed refactoring option) and do what we want.

How is it implemented?

As all new C# 3.0 features, automatic properties is a compiler feature, or syntactic sugar if you will. As the CLR is still at version 2.0, the conversion between automatic and standard properties is done for us by the compiler. Let's have a look at our class in the Reflector.

public class Person { // Fields [CompilerGenerated] private string <FirstName>k__BackingField; [CompilerGenerated] private string <LastName>k__BackingField; // Properties public string FirstName { [CompilerGenerated] get { return this.<FirstName>k__BackingField; } [CompilerGenerated] set { this.<FirstName>k__BackingField = value; } } public string LastName { [CompilerGenerated] get { return this.<LastName>k__BackingField; } [CompilerGenerated] set { this.<LastName>k__BackingField = value; } } }

As you might have guessed, the compiler adds two private properties for us and implements getters and setters.

Now, I know what you're thinking. What if I add a field called <FirstName>k__BackingField to my class? Will the compiler go berserk? Well, sadly, you can't. Field names (or any other name for that matter) cannot start with a "<", so this won't compile to begin with. Oh well.

This is it. Next week we'll talk about Object Initializers. Until then, happy coding.

Posted by dorony | 2 comment(s)
תגים:,