public class ProjectElement {
...
public override bool Equals(object obj) {
if( obj != null
&& obj.GetType().Equals(GetType())) {
ProjectElement otherObject =
(ProjecElement)obj;
return _assemblyPathName.Equals(
otherObject._assemblyPathName);
}
}
...
}
During a debugging session you can use the QuickWatch as a convenient way to examine variables.
However, be aware of the following. When you use QuickWatch on '_assemblyPathName' in the above example then QuickWatch does not consider the context. E.g. even if you hover over the '_assemblyPathName' part of the expression 'otherObject._assemblyPathName' QuickWatch will just use the member variable of 'this', which not in all cases will have the same value.
If you want to be on the safe side then select the entire expression you would like to inspect, e.g. all of 'otherObject._assemblyPathName'. After that select QuickWatch.
I think this is a shortcoming of the QuickWatch feature since it displays the content of a variable that you didn't want to look at, and you might not even notice that you are looking at something different of a similar name.
If one of you Microsofties are reading this maybe you could consider this as an improvement for the next release of Visual Studio? Thank you!
Comments, how-to's, examples, tools, techniques and other material regarding .NET and related technologies.
Sunday, May 11, 2008
Weakness in VS Debugger
Thursday, May 08, 2008
Implementing Properties: Basic Considerations
public class Foo { private string _bar; }Now we want to add an accessor aka the getter:
public class Foo { public string Bar { get { return _bar; } private string _bar; }This has been the easy part. There is not really a lot that can go wrong.
It starts to become more interesting when you add a modifier aka a setter. In it's most simple form you could write:
public class Foo { public string Bar { get { return _bar; } set { _bar = value; } private string _bar; }Easy you think. But hang on. There is more to it. You may want to decide whether it is acceptable to pass in a null reference or not. Whether you allow for null or not is a decision that should be made based on a number of factors. One way to find out is to look at all the places in your code where the getter is used. What would happen to that code if null would be returned? For example:
Foo foo = new Foo(); ... if( foo.Bar.Length > 25 ) { ... } ...In that case if null was returned this piece of code would crash. You could fix this issue by checking for nullness:
Foo foo = new Foo(); ... if( foo.Bar != null && foo.Bar.Length > 25 ) { ... } ...This certainly work but you pay the price of a slightly less readable code. In addition you may have to have this in a lot of places. So in essence you may decide that the property Foo.Bar doesn't allow for null values. The code for class Foo would then look as this:
public class Foo { public string Bar { get { return _bar; } set { if( value != null ) { _bar = value; } } private string _bar; }This clearly provides the benefit of Foo.Bar never being null since upon initialization _bar will be initialized with string.Empty or "".
But again this comes at a price. The setter simply swallows the attempt to set Foo.Bar to null. This might be desirable. I personally prefer that a class doesn't swallow incorrect things but instead fails fast. In this particular case I would want my code to indicated the error by throwing an exception:
public class Foo { public string Bar { get { return _bar; } set { if( value != null ) { _bar = value; } else { throw new ArgumentNullException("value"); } } private string _bar; }You see that although this is a simple property implementation it can already require quite a few decisions to be made and aspects to be considered.
To close off this particular post, I'd like to also bring performance considerations into the picture. What if the setter needs to validate any new value against a remote system such as a service? Let's look at the possible code:
public class Foo { public string Bar { get { return _bar; } set { if( value != null ) { if( _validationService.IsPermitted(value) ) { _bar = value; } else { throw new ArgumentOutOfRangeException("value"); } } else { throw new ArgumentNullException("value"); } } private string _bar; private ValidationService _validationService = new ValidationService(...); }Calling IsPermitted() can be quite expensive. So how to avoid this? Here is one possible solution:
public class Foo { public string Bar { get { return _bar; } set { if( _bar != value ) { if( value != null ) { if( _validationService.IsPermitted(value) ) { _bar = value; } else { throw new ArgumentOutOfRangeException("value"); } } else { throw new ArgumentNullException("value"); } } } private string _bar; private ValidationService _validationService = new ValidationService(...); }With this implementation the validation service is called only if the value has actually changed. Certainly if the set of permitted values is dynamic this implementation would not make the cut. With this post I want to demonstrate that even property that looks like an easy thing to do already requires a lot of considerations. We even touched performance briefly. It is important that we are aware of all of these aspects when implementing and testing such a property. There are more aspects to this but I think I've made my point. Even with simple things like properties there are already a quite a few aspects to consider.
Sunday, April 27, 2008
Codeplex, IE, and Firefox
Saturday, April 26, 2008
Accessing Installation Properties in Custom Actions
/TargetDir="[TARGETDIR]\"Please note the trailing backslash, which you only need to use when you surround the property in double quotes. However, as a safety measure I suggest making it a habit to always add the double quotes and the backslash. Remember paths can and will contain spaces! In some examples on the internet the backslash may be mentiond in the text but not be included in the code sample. If you leave the backslash out you'll see a message box containing "error code 2869". However, this article makes it clear that you must add the trailing backslash if you use the double quotes. Also, if you want to pass more than one property separate them by a single space, e.g.
/TargetDir="[TARGETDIR]\" /UserDir="[PersonalFolder]\"Then in your custom action implementation - a class derived from System.Configuration.Install.Installer - you can access it in the following way (C# here, but similar in other .NET languages):
string targetDir = Context.Parameters["TargetDir"];That's all.
Two More Tips for Debugging Custom Actions
Visual Studio: Access denied when attaching debugger to process
Thursday, April 17, 2008
MySQL closed-source: What's the alternative?
Wednesday, April 16, 2008
ReSharper 3.1: More Details
Tuesday, April 15, 2008
What's next for csUnit?
ReSharper 3.1 in Visual Studio
Tuesday, April 08, 2008
ControlPaint and Vista
Wednesday, April 02, 2008
Property Getters with Bad Manors
public static int Counter {
get {
int cnt = counter;
counter = 0;
return cnt;
}
}Ok, the documentation says that calling this getter will reset the counter. However...
Still, in my opinion this is bad coding practice. Getters shouldn't modify the object. The reason for that is that some IDE's use the getters for displaying object data in debugging sessions. As a consequence debugging code and looking at the member of this object influences the outcome of the debugging session. I call this bad manors of that getter.
The better approach would have been to use a method with a more intuitive name for example "ReadAndResetCounter()". That would a) avoid accidental modification during debugging sessions, b) follow the good coding practice of getters being non-modifying accessors, and c) would express the actual functionality of the code in a more understandable way.
Some recommendations as a take-away:
- Don't implement getters that modify the object
- Instead use a method with a descriptive name
That way you will make it easier for other engineers to use your code and/or library.
(Now I'm wondering how long it will take until Charlie reads this. I'm sure he will agree with me!)
Monday, March 31, 2008
"Location is not available" on Vista
- "Preparing your desktop..." for an extended period of time
- "Location is not available" after you log in
- Desktop looks more like XP and has lost the Aero look-and-feel
I don't know what the reason for this was. Maybe it was relating to my Vodem to not being able to survive stand-by and/or hibernate. Maybe it was because Vista decided to run some lengthy checks, like CHKDSK. The event logs don't give a clue.
Resolution: Reboot another time.
Monday, March 24, 2008
csUnit 2.3 available
unresolved external symbol ?.cctor@@$$FYMXXZ
Monday, March 17, 2008
csUnit, Visual Studio 2008, Vista, .NET 3.x
Thursday, March 13, 2008
csUnit Sources About To Be Moved to Subversion
Visual Studio: "Unable to find manifest signing certificate in the certificate store"
"Unable to find manifest signing certificate in the certificate store"As I was sure that I wasn't using any certificate to sign the assembly I couldn't understand the reason for this error message and the integrated help system for Visual Studio wasn't a big help either. It turned out that I had to manually go into the *.csproj file and remove the following three lines that were apparently left over from some past experiments with signing using a certificate:
<manifestcertificatethumbprint>...</manifestcertificatethumbprint> <manifestkeyfile>...</manifestkeyfile> <generatemanifests>...</generatemanifests> <signmanifests>...</signmanifests>After I had removed those lines I reloaded the project and the solution rebuilt just fine. There is more information on this subject at a Microsoft Forum.