Professional Documents
Culture Documents
Visual Studio offers tons of useful debugging features and allows you to step through your code
line-by-line. However, there are times when you don’t want to step through your application, but
want to make it output simple text strings with variable values, etc.
Enter the System.Diagnostics.Debug class and its Write* methods. By using the Debug class, you
can output messages similarly to the way the Win32 API function OutputDebugString. However,
the beauty of the Debug class is that when you build your application using the default Release
configuration in Visual Studio, no code lines are generated for your Debug.Write* class. This
means there’s no performance penalty for using the Debug class in release code.
To use the Debug class, simply add the “using System.Diagnostics;” statement to your
C# code file, and call Debug.Write:
Debug.Write("Hello, Debugger!");
In addition to Write, you have the possibility to call WriteIf, WriteLine and WriteLineIf. For
example:
When you are debugging your application under the Visual Studio debugger, all the messages that
are sent out by your Write method calls end up in the Output window (View / Output menu
command or Ctrl+W,O on the keyboard). However, if you are running your application outside the
debugger (say, by starting it from Windows Explorer), you can still view the messages using tools
like DebugView from Sysinternals.
Remember, if you build your application using the default Release configuration, even
DebugView won’t show your messages because the Debug.Write* calls are eliminated altogether.
You can also control code generation by defining the DEBUG conditional directive.
Tip: The .NET debugging/tracing architecture also allows you to redirect debugging messages to
different destinations, such as text files. See the help topic “Trace Listeners” for more information.
It is a common practice to store passwords in databases using a hash. MD5 (defined in RFC 1321)
is a common hash algorithm, and using it from C# is easy.
Here’s an implementation of a method that converts a string to an MD5 hash, which is a 32-
character string of hexadecimal numbers.
An example call:
C3FCD3D76192E4007DFB496CCA67E13B
To make the hex string use lower-case letters instead of upper-case, replace the single line inside
the for loop with this line:
sb.Append(hash[i].ToString("x2"));
Sometimes, you might want to make your application a bit more audible. If you are using .NET
2.0, you can utilize the new System.Media namespace and its SystemSound and SystemSounds
classes.
The SystemSounds class contains five static properties that you can use to retrieve instances of the
SystemSound class. This class in turn contains the Play() method, which you can use to play the
wave file associated with the sound in Windows Control Panel. Note that the user can also disable
all sounds altogether, which would mean that no sound can be heard through the computer
speakers.
To play for example the classical beep sound, you could use the following code:
System.Media.SystemSounds.Beep.Play();
Similarly, you could play the “Question” sound with this code:
System.Media.SystemSounds.Question.Play();
The System.Media namespace is defined in System.dll, so there are no new DLLs you would need
to add to your project’s references to use the above code.
Often, you need a way to monitor your applications once they are running on the server or even at
the customer site -- away from your Visual Studio debugger. In those situations, it is often helpful
to have a simple routine that you can use to log messages to a text file for later analysis.
Here’s a simple routine that has helped me a lot for example when writing server applications
without an user interface:
using System.IO;
LogMessageToFile("Hello, World");
The current date and time are automatically inserted to the log file along with your message.
When you have struct objects as the key in a hashtable, the lookup operation of the hashtable
performs miserably. This can be attributes to the GetHashCode() function which is used internally
to do the lookup.
If a struct contains only simple value types (int, short, etc.), the algorithm which computes the
GetHashCode creates hashes which fall into mostly the same bucket.
Example, lets say, the hashtable creates 10 buckets. Then, most probably, all the keys are being put
into the same bucket. Hence when a lookup is performed, the .NET runtime has to traverse
through this entire bucket to get the value.
Hence, instead of the lookup operation being O(1), it becomes O(n) on an average case.
To overcome this drawback, consider overriding the GetHashCode() function and making the life
easier for the .NET Runtime.
An example would be to create a string by merging all your value types in the struct and joining
them by using a special character as a demarcator.
Since your struct is a lookup criteria, it is sure that all the struct values will be different, and hence
the string generated is guaranteed unique.
Now the string generated has a method(GetHashCode()), since it is derived from System.Object
(like all other objects). Just return the output of this API. A code example will help to understand
better.
struct
{
int a;
short b;
public struct(int _a, short _b)
{
a = _a;
b = _b;
}
public override int GetHashCode()
{
string hash = a.ToString() + ":" b.ToString();
return hash.GetHashCode();
}
}
Since you are generating hashcode explicitly which is guaranteed to be unique, it will boost the
performance of your lookup.
Reference: http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/cpref/html/frlrfsystemobjectclassgethashcodetopic.asp
[Author: SantoshZ]
All the /target: options except module create .NET assemblies. Depending on the
option, the compiler adds metadata for the operating system to use when loading the
portable executable (PE) file and for the runtime to use in executing the contained
assembly or module.
module creates a module. The metadata in the PE does not include a manifest.
Module/s + manifest make an assembly - the smallest unit of deployment. Without the
metadata in the manifest, there is little the runtime can do with a module.
exe creates an assembly with an entry point, but sets the Subsystem field of the
PE header to 3 (Image runs in the Windows character subsystem - see the
_IMAGE_OPTIONAL_HEADER structure in winnt.h). If you ILDASM the PE, you will see
this as .subsystem 0x0003. The OS launches this as a console app.
winexe sets the Subsystem field to 2. (Image runs in the Windows GUI
subsystem). The OS launches this as a GUI app.
[Author: SantoshZ]
See also:
Chapter 3 of Inside Microsoft .NET IL assembler (Serge Lidin, Microsoft Press)
Metadata and the PE File Structure at MSDN
An In-Depth Look into the Win32 Portable Executable File Format - Part 1 and Part 2
(Matt Pietrek, MSDN Magazine)
The difference is that the value of a static readonly field is set at run time, and can
thus be modified by the containing class, whereas the value of a const field is set to a
compile time constant.
In the static readonly case, the containing class is allowed to modify it only
static readonly is typically used if the type of the field is not allowed in a const
declaration, or when the value is not known at compile time.
Remember that for reference types, in both cases (static and instance) the readonly
modifier only prevents you from assigning a new reference to the field. It specifically
does not make immutable the object pointed to by the reference.
class Program
{
public static readonly Test test = new Test();
}
}
class Test
{
public string Name;
}
On the other hand, if Test were a value type, then assignment to test.Name would be an
error.
Strictly speaking you can't, since const can only be applied to a field or local whose value is
known at compile time.
In both the lines below, the right-hand is not a constant expression (not in C#).
However, there are some workarounds, depending on what it is you want to achieve.
If want a proper .NET array (System.Array) that cannot be reassigned, then static readonly will do
for you.
For example:
[Flags]
public enum Role
{
Administrator = 1,
BackupOperator = 2,
// etc.
}
[RoleAttribute(RoleAttribute.DefaultRole)]
public class DatabaseAccount
{
//..............
}
RoleAttribute, instead of taking an array, would only take a single argument of flags (appropriately
or-ed). If the underlying type of the Role enum is long or ulong, that gives you 64 different Roles.
[Author: SantoshZ]
Admitedly, this is not a question specific to C#, but it is one I have seen enough C#
programmers ask, and the ability to set environment variables is new to the Whidbey
release, as is the EnvironmentVariableTarget enumeration which lets you separately
specify process, machine, and user.
Brad Abrams blogged on this way back at the start of this year, and followed up with
a solution for pre-Whidbey users.
[Author: SantoshZ]
Now that Whidbey has been out in Beta for more than a few months, it seems worth revisiting some
frequently asked questions which have different (better?) answers now.
For the yes part of the answer, after building, go to the Output Window, select "Show Output from: Build",
and about half way down you will see a section like this:
Task "Csc"
Now for the no part of the answer. The project system does not actually execute this command line as part of
the build process. As the output says, the IDE directly calls its own in-process compiler to perform the
equivalent. However, in all cases, you should get the same results using the command line suggested in the
output window. If you don't, you could be looking at a bug.
Note: before you cut and paste the build output to the command line, remember to add the path to CSC.EXE
[Author: SantoshZ]
In the unmanaged world, it was quite common to intercept Win32 messages as they were plucked
off the message queue. In that rare case in which you wish to do so from a managed Windows
Forms application, your first step is to build a helper class which implements the IMessageFilter
interface. The sole method, PreFilterMessage(), allows you to get at the underlying message ID, as
well as the raw WPARAM and LPARAM data. By way of a simple example:
At this point you must register your helper class with the Application type:
public mainForm()
{
// Register message filter.
Application.AddMessageFilter(msgFliter);
}
…
}
At this point, your custom filter will be automatically consulted before the message makes its way
to the registered event hander. Removing the filter can be accomplished using the (aptly named)
static Application.RemoveMessageFilter() method.
Given that the .NET platform encourages binary reuse of types, it is commonplace to set
references to external assemblies using the Visual Studio .NET Add Reference dialog box. Many
programmers (especially those of the C(++) ilk) fear that adding unnecessary external references
can result in a bit of 'code bloat'. Nothing could be further from the truth. When you add assembly
references or make use of the 'using' keyword, csc.exe will ignore any assembly which you have
not actually made use of in your code. Thus, if you were to set a reference to System.Data.dll and
System.Windows.Forms.dll but only authored the following code:
using System;
using System.Data; // Ignored.
using System.Windows.Forms; // Ignored.
As you may be aware, when you open up a .NET assembly using ildasm.exe, the MANIFEST icon
may be double clicked to open a window describing the binary under investigation. At the very
top, you will see a list of each external assembly the current assembly was compiled against
(provided that it was actually used):
Bottom line? Don't waist your time stripping out unused 'using' statements or assembly references
from your application. The C# compiler will do so for you automatically.
Okay, I admit this is a rather lame tip which can hardly qualify as 'insightful', however this is one
of my favorite features of Visual Studio .NET (as well as previous editions of the Visual Studio
product line) which many folks are (surprisingly) unaware of. Under the View menu you will find
a menu item named 'Full Screen'. When activated, the only window displayed will be the active
document. This is especially helpful for those working on low resolution monitors, given that the
size of your code window can shrink dramatically if you have too many windows docked within
the IDE. To escape from full screen, just click the Full Screen button floating over your code
window.
Like other languages in the C-family, C# supports a set of 'preprocessor' directives, most notably
#define, #if and #endif (technically, csc.exe does not literally have a preprocessor as these symbols
are resolved at the lexical analysis phase, but no need to split hairs…).
The #define directive allows you to set up custom symbols which control code compilation. Be
very aware that unlike C(++), C#'s #define does not allow you to create macro-like code. Once a
symbol is defined, the #if and #endif maybe used to test for said symbol. By way of a common
example:
#define DEBUG
using System;
When you use the #define directive, the symbol is only realized within the defining file. However
if you wish to define project wide symbols, simply access your project's property page and
navigate to the "Configuration Properties | Build" node and edit the "Conditional Compilation
Constants" edit field. Finally, if you wish to disable a constant for a given file, you may make use
of the #undef symbol.