(FAQ) C# Frequently Asked Questions
FAQ: C# Frequently Asked Questions Page2
Leverage the C# Preprocessor
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;
public class MyClass
{
public static void Main()
{
#if DEBUG
Console.WriteLine("DEBUG symbol is defined!");
#endif
}
}
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.
Avoiding Type Name-Clashes using 'using'
You are already aware that the C# using keyword allows you to supply hints to the compiler regarding the fully qualified name of the types within a given *.cs file. However, what you may not know is that the using keyword also allows you to build aliases (very helpful for prevent name clashes). Assume you have the following two namespace definitions:
namespace My2DShapes
{
public class Hexagon{}
}
namespace My3DShapes
{
public class Hexagon{}
}
Now assume you wish to create an instance of the 3D Hexagon from the following application:
using My2DShapes;
using My3DShapes;
public class MyApp
{
public static void Main()
{
// Error! Which Hexagon?
Hexagon h = new Hexagon();
}
}
This name clash can be resolved quite simply by building the following alias:
using My2DShapes;
using The3DHex = My3DShapes.Hexagon;
public class MyApp
{
public static void Main()
{
// This really creates a new My3DShapes.Hexagon.
The3DHex h = new The3DHex();
}
}
Build 'Consistent' .NET assemblies with FxCop
The term 'best practices' sends chills up the spines of many people. Reason being, what is 'best' for one is 'horrible' for another. However, if you are interested in ensuring that your custom .NET assemblies are in-sync with the coding guidelines proposed by Microsoft, you will want to obtain a freely downloadable tool named fxcop.exe (FxCop may be downloaded from http://www.gotdotnet.com/team/fxcop/).
This tool allows you to load any .NET binary and run it though a battery of tests which will check how your assembly stacks up against the coding standards upheld in the Base Class Libraries (including numerous .NET 'best practices'). Even better, you can create custom rules and ignore those you don't care about. This Windows Forms application is quite intuitive, however be aware that fxcop.exe ships with the requisite online help.
Simplified Interface Implementation a la VS .NET 2003
Another helpful feature of VS .NET 2003 has to do with the implementation of interface types. As you know, when a class or structure agrees to implement a given interface, it must implement all of the members. Assume you wish to support an interface containing six members. While you could type in the member definitions by hand, you will save yourself time (and hand-cramps) by using the following shortcut. Once you type the name of an interface at the type declaration, VS .NET pops up an invitation to (once again) hit the Tab key:
public class SomeClass
: ISomeInterface // Message pops up to hit the Tab key…
{…}
Once you do, VS .NET will automatically write stub code for each and every member.
Simplified Event Handling a la VS .NET 2003
Working with events under the .NET platform requires you to be aware of a number of details. For example, if you know the name of the event you wish to handle, you must then know the name of the related delegate type. Once you know that much, you must then be aware of the correct signature of the delegate target method.
To simplify matters, VS .NET 2003 will now automatically display the correct delegate name as well as write a prototype for the delegate target. To try this out yourself, create a Windows Forms application and place a single Button type onto the designer. Next, type the following code within InitializeComponent():
this.Button1.Click += // Message pops up to tell
// you to hit the Tab key…
Once you hit the Tab key, you will find the correct delegate is already in place. Hit the Tab key again and you will receive a delegate target method of the correct signature. Be aware that this shortcut works for any event, custom or standard (GUI-based or not).
Integrate ildasm.exe into VS .NET 2002
VS .NET allows you to add any number of external tools to the Tools menu. One very helpful technique is to configure ildasm.exe to automatically load up the current assembly being compiled. While VS .NET 2003 sets this up automatically, VS .NET 2002 may update the Tools menu manually. To do so, activate the Tools -> External Tools menu item. The 'Title' edit field allows you to supply the display name of your new menu item. In the 'Command' filed, type in the path to ildasm.exe (for example, C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin\ildasm.exe). Finally, and most importantly, be sure to specify $(TargetPath) in the 'Arguments' field. Once you have done so, you can simply activate this menu item and the assembly under development will automatically be loaded into ildasm.exe.
More info on ildasm.exe
Add Custom .NET Assemblies to the Add Reference Dialog
As you most likely know by now, the Add References dialog of Visual Studio .NET does not list each and every assembly on your machine, does not directly map to the Global Assembly Cache and does not list your custom assemblies. Typically this limitation is addressed by manually navigating to the *.dll of interest via the 'Browse' button.
However, if you wish to force VS.NET to display your custom assemblies within in the list maintained by the Add Reference dialog, all you need to do is place a copy of the assembly within the 'PublicAssemblies' folder located under C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE. Once you have done so, lo' and behold, your custom *.dlls are listed automatically.
Leverage C# Response Files at the Command Line
Although I'd bet most of you make use of VS .NET as opposed to the raw command line complier, csc.exe can be quite useful in a number of circumstances. However, few of us enjoy typing lengthy command line flags such as:
csc /r: MyAsm.dll;MyOtherAsm.dll /t: winexe /out: myApp.exe *.cs
To lessen your burden, the C# command line compiler supports the use of 'response files'. Simply put, response files are text files which contain all of the command line arguments you wish to feed into the compiler. By convention, these files end with a *.rsp file extension. Thus, assume you have a file named mySettings.rsp:
# Response files support comments.
/r: MyAsm.dll
/r: MyOtherAsm.dll
/t: winexe
/out: myApp.exe *.cs
With this, you can simply specify the name of the response file to use for the current compilation (via the @ symbol):
csc @mySettings.rsp
Be Aware of wincv.exe
When you install the .NET SDK / VS.NET, you are provided with numerous stand alone programming tools, one of which is named wincv.exe (Windows Class Viewer). Many developers are unaware of wincv.exe, as it is buried away under the C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin subdirectory (by default).
This tool allows you to type in the name of a given type in the base class libraries and view the C# definition of the type. Mind you, wincv.exe will not show you the implementation logic, but you will be provided with a clean snapshot of the member definitions.
Utilize the Server Explorer
Visual Studio .NET provides a very interesting view of the world named the Server Explorer (which can be activated from the View menu). While you may already be aware many of these items can be opened within VS .NET for editing (for example, opening a database Table or editing a stored procedure), you may not know that everything is dragable. Let's say you know your application needs to interact with a machine's application event log. Simply open the Event Logs tree and drag the Application icon onto a Forms designer. VS .NET responds by declaring a member variable of type System.Diagnostics.EventLog and modifying InitializeComponent() appropriately:
this.eventLog1.Log = "Application";
this.eventLog1.MachineName = "MainHomeBox";
this.eventLog1.SynchronizingObject = this;
This same behavior holds true for any icon. To take things out for a test drive, try dragging over an icon representing a stored procedure, Windows Service or Message Queue.
Obtain Type Information on the Fly using typeof
All .NET assemblies contain vivid type information which describes the structure of every internal and external type (this can be verified by loading an assembly into ildasm.exe and clicking the ctrl-m keystroke). On a related note, many methods in the .NET base class libraries require you to pass in type information for a given item. When you need to obtain type information for a given method invocation, you have numerous approaches. First, all types inherit the public System.Object.GetType() method:
// Obtain type information from a variable.
SomeType c = new SomeType();
Type t = c.GetType();
INeedYourTypeInfo(t);
While this works, it is overkill to create a type simply to call the inherited GetType() method. To streamline the process, the C# language offers the typeof operator. The benefit is you are not required to create the item in question, rather simply specify the name of the type as an argument:
// Obtain type information via typeof. INeedYourTypeInfo(typeof(SomeType));
Interacting with overloaded operators from overloaded operator challenged languages
Like the C++ language, C# allows you to overload operators for your custom types. For example, assume you have a structure named MyPoint which has overloaded the plus operator. If this is the case, you can 'add' two MyPoints as so:
// Add two MyPoint types to obtain a
// 'bigger' Point.
MyPoint bigPoint = ptOne + ptTwo;
Although this is a very powerful technique, many C# programmers avoid doing so in fear of building non CLS-compliant types. Fear not! Every overloaded operator maps to a 'special' static CIL method which can be invoked by languages which do not natively support directly operator manipulation. In our case, 'operator +' maps to a method named 'op_Addition()'. Given this, a VB.NET programmer could interact with MyPoint as so:
' Add two MyPoint types to obtain a
' 'bigger' Point.
Dim bigPoint as MyPoint = _
MyPoint.op_Addition(ptOne + ptTwo)
How to keep a local variable in scope across a try and catch block?
The following code won't work, because conn goes out of scope before you enter the catch block.
try
{
Connection conn = new Connection();
conn.Open();
}
catch
{
if (conn != null) conn.Close();
}
The fix is simple - just declare conn before entering the try block
Connection conn = null; // Note the assignment to null to avoid error CS0165 - Use of possibly unassigned local variable 'conn'.
try
{
conn = new Connection();
conn.Open();
}
catch
{
if (conn != null) conn.Close();
}
Of course, for this particular example, you could wrap the Connection class in one that implements IDisposable (if it does not already), so that you could then use a using statement instead of extending the scope of the local.
Does C# support variable arguments (vararg's) on methods?
There was a suggestion/question on the Product Feedback site for VS2005 that suggested that the params keyword may not be that well understood.
The params keyword can be applied on a method parameter that is an array. When the method is invoked, the elements of the array can be supplied as a comma separated list.
So, if the method parameter is an object array,
void paramsExample(object arg1, object arg2, params object[] argsRest)
{
foreach (object arg in argsRest)
{ /* .... */ }
}
then the method can be invoked with any number of arguments of any type.
paramsExample(1, 0.0f, "a string", 0.0m, new UserDefinedType());
What is the equivalent to regsvr32 in .NET?
Where you once used Regsvr32 on unmanaged COM libraries, you will now use Regasm on managed .NET libraries.
“Regsvr32 is the command-line tool that registers .dll files as command components in the registry“
“Regasm.exe, the Assembly Registration tool that comes with the .NET SDK, reads the metadata within an assembly and adds the necessary entries to the registry, which allows COM clients to create .NET Framework classes transparently. Once a class is registered, any COM client can use it as though the class were a COM class. The class is registered only once, when the assembly is installed. Instances of classes within the assembly cannot be created from COM until they are actually registered.“
If you want to register an assembly programmatically, see the RegistrationServices class and ComRegisterFunctionAttribute
- guru's blog
- Login or register to post comments

