May 01
I have a friend who is just starting to learn C#, so I am getting some interesting questions whose answers seem obvious to me but apparently not to beginners. Today I answer the question: What’s the best way to initialize Flags enumerations in C#?
As a quick review, here is how Microsoft describes the Flags enumeration: “You can use an enumeration type to define bit flags, which enables an instance of the enumeration type to store any combination of the values that are defined in the enumerator list. (Of course, some combinations may not be meaningful or allowed in your program code.) You create a bit flags enum by applying the System.FlagsAttribute attribute and defining the values appropriately so that AND, OR, NOT and XOR bitwise operations can be performed on them.”
In other words, each enumeration value must correspond to a single, unique bit. So one way to initialize flags is to use integers that are a power of 2. The disadvantage of this method is it’s not easy to see which bit is being set, and errors might creep in enumerations with many flags, especially when you start getting up into the range of 16384, 32768, 65536, and 131072. But there is nothing inherently wrong with this approach either:
[Flags]
public enum DaysOfTheWeek
{
None = 0,
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64,
}
Read the rest of this entry »
Aug 15
An enumerator enables you to iterate over a collection in a foreach loop. You can use foreach to iterate over all C# collection classes, because all C# collection classes inherit from the IEnumerable interface (regular or generic). IEnumerable contains the GetEnumerator method, which returns an enumerator.
Occasionally you may find a need to create a custom enumerator, which used to be somewhat of a challenge until the yield keyword was introduced. Here is how Microsoft describes yield:
The yield keyword signals to the compiler that the method in which it appears is an iterator block. The compiler generates a class to implement the behavior that is expressed in the iterator block. In the iterator block, the yield keyword is used together with the return keyword to provide a value to the enumerator object. This is the value that is returned, for example, in each loop of a foreach statement.
So rather than creating your own enumerator class and managing the enumeration state — which is time consuming and tricky — you can simply write the enumeration logic in the GetEnumerator method, and the yield keyword will automagically wrap your code in a handy-dandy enumerator.
Read the rest of this entry »
Mar 05
When building a C# interface, you may find a need for both public and internal methods, such as:
public class MyClass : IMyInterface
{
public void MyPublicMethod() { }
internal void MyInternalMethod() { }
}
public interface IMyInterface
{
public void MyPublicMethod();
internal void MyInternalMethod();
}
Read the rest of this entry »
Jan 27
To iterate over an IDictionary<x,y> interface, use the KeyValuePair<x,y> structure. Following is a simple example:
Read the rest of this entry »
Jan 26
You may have noticed the first line of XML output generated by XmlWriter or XmlTextWriter shows that the encoding defaults to UTF-16:
<?xml version="1.0" encoding="utf-16"?>
This happens even if you explicitly set the Encoding property in the XmlWriterSettings to something different, such as UTF-8:
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings ();
settings.Encoding = System.Text.Encoding.UTF8;
XmlWriter writer = XmlWriter.Create (sb, settings);
The problem occurs because the StringWriter defaults to UTF-16. (It’s not clear from the example above, but the XmlWriter class uses a StringWriter to output the XML to the specified StringBuilder.)
Read the rest of this entry »
Jan 13
If you want to rename a file in C#, you’d expect there to be a File.Rename method, but instead you must use the System.IO.File.Move method.
You must also handle a special case when the new file name has the same letters but with difference case. For example, if you want to rename “test.doc” to “Test.doc”, the File.Move method will throw an exception. So you must rename it to a temp file, then rename it again with the desired case.
Here is the sample source code:
/// <summary>
/// Renames the specified file.
/// </summary>
/// <param name="oldPath">Full path of file to rename.</param>
/// <param name="newName">New file name.</param>
static public void RenameFile( string oldPath, string newName )
{
if (String.IsNullOrEmpty( oldPath ))
throw new ArgumentNullException( "oldPath" );
if (String.IsNullOrEmpty( newName ))
throw new ArgumentNullException( "newName" );
string oldName = Path.GetFileName( oldPath );
// if the file name is changed
if (!String.Equals( oldName, newName, StringComparison.CurrentCulture ))
{
string folder = Path.GetDirectoryName( oldPath );
string newPath = Path.Combine( folder, newName );
bool changeCase = String.Equals( oldName, newName, StringComparison.CurrentCultureIgnoreCase );
// if renamed file already exists and not just changing case
if (File.Exists( newPath ) && !changeCase)
{
throw new IOException( String.Format( "File already exists:n{0}", newPath ) );
}
else if (changeCase)
{
// Move fails when changing case, so need to perform two moves
string tempPath = Path.Combine( folder, Guid.NewGuid().ToString() );
Directory.Move( oldPath, tempPath );
Directory.Move( tempPath, newPath );
}
else
{
Directory.Move( oldPath, newPath );
}
}
}
Dec 16
When building a Visual Studio project, you may encounter the following error:
The project "MyProject" is not selected for building in solution configuration "Debug|Any CPU".
This error occurs because the project has not been configured to build in your Visual Studio solution. The solution is simple:
Read the rest of this entry »
Oct 23
There may be times when you wish to temporarily load a .NET assembly to inspect it, but you don’t want the assembly to remain in your program’s memory taking up resources. Unfortunately, once your program loads an assembly, there is no way to unload it. The best way is to create a separate AppDomain, load the assembly into that AppDomain, then unload the AppDomain when you are finished.
The following sample code loads a .NET assembly from disk, displays the name of every type defined in the assembly, then unloads the assembly:
AppDomain appDomain = null;
try
{
string path = @"C:myAssembly.dll";
byte[] buffer = File.ReadAllBytes( path );
appDomain = AppDomain.CreateDomain( "Test" );
Assembly assm = appDomain.Load( buffer );
Type[] types = assm.GetTypes();
foreach (Type type in types)
{
Console.WriteLine( type.FullName );
}
}
catch (Exception ex)
{
Console.WriteLine( ex.Message );
}
finally
{
if (appDomain != null)
AppDomain.Unload( appDomain );
}
Oct 12
Most developers use the Process.Start static method to run an external application from within C# code. The Start method launches the external process asynchronously, meaning that your C# code continues executing and does not wait for the process to finish.
But occasionally you may wish to halt your program and wait for the external process to finish. So to launch a process synchronously from a C# application, the key is to create a Process object and call the WaitForExit method after you start the process. Be sure to finish with a call to the process Close method. Here is some sample code:
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo( "notepad.exe" );
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
process.Close();
MessageBox.Show( "Process Complete" );
Oct 11
SN.exe is a Strong Name tool that can sign assemblies, manage strong name keys, and generate and verify signatures. You will typically find it here:
C:Program Files (x86)Microsoft Visual Studio 8SDKv2.0Bin
If you cannot find it there, check “C:Program Files” on 32-bit systems. Also check the folders corresponding to other versions of Microsoft Visual Studio, such as “Microsoft Visual Studio 9.0” etc. If you still cannot find it, run a search on your C: drive.
If SN.exe is not installed on your hard drive, you can download it here:
.NET Framework 2.0 Software Development Kit (SDK)
x86 x64
According to Microsoft, since .NET Framework versions 3.0 and 3.5 are built incrementally on the .NET Framework version 2.0, many of the tools included in the .NET Framework 2.0 SDK are the latest versions available. But just in case, you can download the newest version of .NET:
.NET Framework 4 redistributable package