What are your favorite lesser-known .NET Base Class Library classes and methods?
I didn't know about System.Net.WebClient until it was posted in an answer to a question of mine.
WebClient client = new WebClient ();
client.DownloadFile("http://stackoverflow.com/", "target.html");
client.UploadFile("http://mysite.com/", "hello.txt");
System.Web.UI.WebControls.MailDefinition
"The MailDefinition class can be used by controls to create a MailMessage object from a text file or a string that contains the body of the e-mail message. Use the MailDefinition class to simplify creating predefined e-mail messages to be sent by a control."
For some reason many people don't kow about System.Text.StringBuilder. I couldn't live without it!
This saves a lot of typing on strings:
string.IsNullOrEmpty()
and
string.IsNullOrWhiteSpace() // .NET 4 only
Also a hidden gem using events; when declaring an event, a nice way to make sure you never need to check if it's null, is by initializing it to an empty anonymous delegate at declaration time:
public event EventHandler MyASimpleEvent = delegate {};
System.Diagnostics.ConditionalAttribute. It makes the compiler ignore methods or classes that should only be active in certain build profiles. EG:
[Conditional("DEBUG")]
private void DumpProperties()
{
foreach (PropertyInfo prop in this.GetType().GetProperties())
Console.WriteLine(prop.GetValue(this, null));
}
Path class. I can't count the times the lack of its usage came up in code-reviews. People tend to go for the string concatenations and sub-stringage instead of using Path.Combine and Path.GetFileNameWithoutExtension, among others.
A cool way to log the name of the current method you're in:
string myMethodName = MethodBase.GetCurrentMethod().Name;
Console.WriteLine(myMethodName);
System.Runtime.InteropServices.Marshal
I hate having to do interop, and particularly PInvoke, but there are all kinds of goodies in Marshal for turning function pointers into delegates, and vice versa, turning Win32 error codes into something a little more helpful (often only a little though), and so on.
System.Security.SecureString - More people should be aware of this if their program accepts passwords or passphrases, or stores credit card numbers in memory. SecureString values are stored encrypted (obfuscated, rather), but most importantly, they are never swapped to disk and can be disposed of immediately when you're done with them.
They're tricky to use because you can only build them one character at a time (to encourage you to build them by capturing keystrokes as the user types their password), and require three lines of code to recover and then wipe their plain text, but when used properly they can make a program more secure by avoiding the virtual-memory vulnerability.
// Make a SecureString
SecureString sPassphrase = new SecureString();
Console.WriteLine("Please enter your passphrase");
ConsoleKeyInfo input = Console.ReadKey(true);
while (input.Key != ConsoleKey.Enter)
{
sPassphrase.AppendChar(input.KeyChar);
Console.Write('*');
input = Console.ReadKey(true);
}
sPassphrase.MakeReadOnly();
// Recover plaintext from a SecureString
// Marshal is in the System.Runtime.InteropServices namespace
try {
IntPtr ptrPassphrase = Marshal.SecureStringToBSTR(sPassphrase);
string uPassphrase = Marshal.PtrToStringUni(ptrPassphrase);
// ... use the string ...
}
catch {
// error handling
}
finally {
Marshal.ZeroFreeBSTR(ptrPassphrase);
}
Edit: At the end of the example the SecureString is converted into a regular managed string, which makes it vulnerable again (be sure to use the try-catch-finally pattern to Zero the string after you're done with it). SecureString's use is in reducing the surface-area of attack by limiting the number of copies the Garbage Collector will make of the value, and reducing the likelihood of being written to the swap file.
The .Net framework is gaining more support for SecureStrings that help eliminate the need to decrypt it. The PasswordBox control in WPF stores its value in a SecureString, System.Diagnostics.ProcessStartInfo's Password property takes a SecureString, and so does the constructor for X509Certificate2. Some third party components are beginning to take it as native currency, too.
Most definitely String.Join(char separator, string[] list)
to create "a,b,c"
from {"a","b","c"
}. This alleviates keeping track of a boolean to check whether the first item is already used.
The BitConverter.ToString method is very useful when working with binary data. I use it for debugging, traces and within unit testing.
It will take a byte array and return a printable string representation - something like "04-08-01-23-45-67-89-AB-CD-EF".
I also use Regex.Split(string, string) for splitting a delimited strings.
It is somewhat similar to String.Split(), but using Regex.Split() is much more intuitive: Regex.Split() result string array only contain the data you need, while String.Split() result also contains the delimiters.
System.Diagnostics namespace contains many "hidden" gems. I have used extensively the DebuggerStepThroughAttribute
, I have subclassed many times the TraceListener
class and I want to see in more detail the PerformanceCounter
.
System.Convert is a lot nicer than people think.
It's a bit more forgiving on what you put in. Use Reflector to see how it converts between different types.
Ints are defaulted to 0 from bad input, bools to false and so on.
It's made int.Parse, bool.Parse and all other .Parse almost obsolete for me. TryParse is still usefull for the most secure parsing.
System.Environment is one of my favorites. Especially the Workingset property.
System.Web.VirtualPathUtility
Provides utility methods for common virtual path operations.
http://msdn.microsoft.com/en-us/library/system.web.virtualpathutility.aspx
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim sb As New StringBuilder()
Dim pathstring As String = Context.Request.FilePath.ToString()
sb.Append("Current file path = " & pathstring & "<br />")
sb.Append("File name = " & VirtualPathUtility.GetFileName(pathstring).ToString() & "<br />")
sb.Append("File extension = " & VirtualPathUtility.GetExtension(pathstring).ToString() & "<br />")
sb.Append("Directory = " & VirtualPathUtility.GetDirectory(pathstring).ToString() & "<br />")
Response.Write(sb.ToString())
Dim sb2 As New StringBuilder()
Dim pathstring1 As String = Context.Request.CurrentExecutionFilePath.ToString()
sb2.Append("Current Executing File Path = " & pathstring1.ToString() & "<br />")
sb2.Append("Is Absolute = " & VirtualPathUtility.IsAbsolute(pathstring1).ToString() & "<br />")
sb2.Append("Is AppRelative = " & VirtualPathUtility.IsAppRelative(pathstring1).ToString() & "<br />")
sb2.Append("Make AppRelative = " & VirtualPathUtility.ToAppRelative(pathstring1).ToString() & "<br />")
Response.Write(sb2.ToString())
End Sub
This is cool. VisualStyleInformation Class provides a lot of information about the current visual style of the operating system.
System.Diagnostics.Debugger.Break() is used by virtually everyone but is very convenient for debugging .NET services.
NetworkChange.NetworkAvailabilityChanged Event makes it easy to monitor network availability.
If you are drawing custom Windows Forms controls, then the following classes are essential for your OnPaint() method (or Paint event):
using System.Windows.Forms;
- ControlPaint
- TextRenderer
- *Renderer (eg ButtonRenderer, TextBoxRender, etc)
These classes all provide methods that will do most of the drawing work for you and keep your controls looking professional and native.
TextRenderer.MeasureText() is great for figuring out how large to draw your text. So often I see:
// this == something derived from Control
Graphics g = this.CreateGraphics();
Size size = g.MeasureString(this.Text, this.Font).ToSize();
g.Dispose();
When really all you need is:
Size size = TextRenderer.MeasureText(this.Text, this.Font);
The former is how you did it in 1.0 and 1.1; the latter is how you do it in 2.0+. It's much cleaner, doesn't requiring creating an object which must be disposed, and doesn't leave you open to accidentally not disposing of a resource. Plus if you use TextRenderer.DrawText() your text will look better and localize better. This stuff just plain rocks when you're doing custom controls.
Edit: On the I18N/G11N front, here's more info: the shaping engines for international text have been updated quite a bit in the Uniscribe subsystem of the Windows operating system, but not in GDI+ subsystem. So sometimes things looked strange/wrong if your .NET app was using the Graphics based method (AKA, GDI+). However, using the TextRenderer approach (AKA, Uniscribe) eliminates these problems and allows you to render text correctly (perfectly?) in the new locales introduced with Windows XP SP2 (such as Bengali and Croatian). (Caveat emptor: I have no idea how or even if either of these methods play with vendor specific extensions to specific code pages.)
Here's a little snippet to tell which class/method the call is coming from. Useful in some special situations:
StackFrame frame = new StackFrame(1);
frame.GetMethod().Name; //Gets the current method name
MethodBase method = frame.GetMethod();
method.DeclaringType.Name //Gets the current class name
String.Format(). Allows you to get rid of the wonkiness of "This" + " is" + " my favorite " + " Application";
System.Diagnostics.DebuggerDisplay
When you're debugging, if the class is attributed, visual studio will display the information on mouse-over. It even allows you to put in properties of private fields, etc.
[System.Diagnostics.DebuggerDisplay("MyClass: ID={ID} Name={Name} ChildName={_child.Name}")]
Ref: msdn
I like to use System.Collections.CaseInsensitiveComparer to compare strings.
TypeConverter class
It saved me a lot of time. And it helped Stack Overflow users to solve their problems:
public static int Compare(string strA, string strB, bool ignoreCase)
Great to compare two strings with possible difference in letter case.
System.Reflection.Assembly.GetExecutingAssembly.Location
Gets the path (and name) of the current running application.
I have a few related commands at my Blog
I just found:
System.Security.Cryptography.ProtectData
Used to encrypt data for the current user or the local machine.
Using StackFrame to get information about calling method and running class. You can travel the stack and get the methodName, calling calss etc. You can get the stackFrame using
StackFrame frame = new StackFrame(n);
Where n is the layer above the current call And then you can retrive information by using its properties. for example use the following the get the information of the calling method:
MethodBase methodBase = frame.GetMethod();
System.Data.Common.DbConnectionStringBuilder
and
System.Data.SqlClient.SqlConnectionStringBuilder
These allow you to build a connection string in a programmatic way without have to remember the specific syntax.
Documentation: DbConnectionStringBuilder on MSDN
HashSet<T>
. It is a new class in the .NET Framework 3.5 and is very similar to List<T>
only better.
http://blogs.msdn.com/bclteam/archive/2006/11/09/introducing-hashset-t-kim-hamilton.aspx
System.Web.Security.FormsAuthentication
.HashPasswordForStoringInConfigFile(string password, string format)
Does the simple and common task of getting the MD5 or SHA1 hash of a given string. Since almost every system I have ever written stored password hashes instead of encrypted data or the plaintext, this is a godsend to avoid mucking about with the Crypto stuff.
The DebuggerStepThroughAttribute is great for properties and also for those helper functions that you have no desire to step through. Unfortunately, it seems rarely known:
http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggerstepthroughattribute.aspx
Not really hidden but:
- System.Drawing.Printing.PrinterSettings.InstalledPrinters: Returns a collection with all printer names installed in the machine.
Getting the list of countries. Useful for populating the drop down box.
foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures & ~CultureTypes.NeutralCultures
{
RegionInfo ri = new RegionInfo(ci.LCID);
Console.WriteLine(ri.EnglishName);
}
ref: http://jdconley.com/blog/archive/2007/09/05/list-of-country-names.aspx#1
Expanding the My Namespace has always been useful to me
Namespace My
<Global.Microsoft.VisualBasic.HideModuleName()> _
Friend Module MyStuff
Sub Foo()
End Sub
End Module
End Namespace
I'd have to say System.ComponentModel.BackgroundWorker
.
It's not exactly easy to use, because you still have to understand how asynchronous method calls work, and you have to know about avoiding cross-thread exceptions, using Invoke
to update the UI, etc. But it's considerably easier to use than System.Threading.Thread
, which is what a lot of developers gravitate towards when they need to implement a background process.
More of a runtime feature, but I recently learned that there are two garbage collectors. The workstation gc and the server gc. Workstation is the default, but server is much faster on multicore machines.
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
Be careful. The server gc requires more memory.
System.Runtime.Remoting.Proxies.RealProxy.
This class is pretty esoteric and normally only used in weird remoting scenarios; however, I have used it for the ability to dynamically implement an interface. It is also used by some mocking frameworks for the same purpose. See also Extending RealProxy.
Very helpful class to measure performance System.Diagnostics.StopWatch
See detailed posts here
MatchEvaluator Delegate: Represents the method that is called each time a regular expression match is found during a Replace method operation.
You can play default windows sounds this way :
System.Media.SystemSounds.Beep.Play();
...
System.Media.SystemSounds.Question.Play();
In line with String.IsNullOrEmpty().....
String.Empty
usage:
string s = String.Empty;
//OR
string s = string.Empty;
instead of
string s = "";
WeakReference. Extract from here ...
The garbage collector cannot collect an object in use by an application while the application's code can reach that object. The application is said to have a strong reference to the object.
A weak reference permits the garbage collector to collect the object while still allowing the application to access the object.
This can be used to implement weak events, see here
Deep comparison of XmlTrees
Compares the values of two nodes, including the values of all descendant nodes.
Tired of typing the unwieldy
string.Equals(x, y, StringComparison.CurrentCultureIgnoreCase)
?
Instead, try one of the properties on the StringComparer class:
Instead of the above, you can type:
StringComparer.CurrentCultureIgnoreCase.Equals(x, y);
Even though it's only slightly shorter, it's nice because it keeps the focus on the two things you're comparing, without the distraction of the StringComparison.CurrentCultureIgnoreCase
parameter. And you can break it up if you like:
var comparer = StringComparer.CurrentCultureIgnoreCase;
comparer.Equals(x, y);
This isn't really a method but just something I found in the String class source:
// The Empty constant holds the empty string value.
// We need to call the String constructor so that the compiler doesn't mark this as a literal.
// Marking this as a literal would mean that it doesn't show up as a field which we can access
// from native.
public static readonly String Empty = "";
FormatterServices.GetUninitializedObject
Creates a new instance of a type without calling any constructor. This will work with private constructors, non-parameterless-constructors, any type of constructor (since they aint called).
I believe this is the only way to ensure that a static constructor on a type is executed if you only have a Type instance. (You can not invoke it with reflection, and the Activator may fail due to nonmatching constructors.)
A somewhat esoteric problem, and solution.
Ignore Attribute on Unit-Tests for ignoring slow performance tests during development
Decimal
preserves trailing zeros :
decimal x = 1.0m;
decimal y = 1.00m;
decimal z = 1m;
Assert.IsTrue(x == y);
Assert.IsFalse(x.ToString() == y.ToString());
Assert.AreEqual("1.0", x.ToString(CultureInfo.InvariantCulture));
Assert.AreEqual("1.00", y.ToString(CultureInfo.InvariantCulture));
Assert.AreEqual("1", z.ToString(CultureInfo.InvariantCulture));
Assert.AreEqual("1.000", (x*y).ToString(CultureInfo.InvariantCulture));
This behavior is documented in the MSDN library.
The decimal.Parse
method keeps track of trailing zeros too :
decimal x= decimal.Parse("1.0", CultureInfo.InvariantCulture);
decimal y= decimal.Parse("1.00", CultureInfo.InvariantCulture);
Assert.AreEqual("1.0", x.ToString(CultureInfo.InvariantCulture));
Assert.AreEqual("1.00", y.ToString(CultureInfo.InvariantCulture));
Really useful class is System.Diagnostics.Stopwatch. It saves you from inventing a bicycle every time you need to measure time. It's really helpful when you need to make some time dependent work (perhaps periodic) in some thread.
System.Net.Mail.MailAddress - no more regexp for server-side email address validation ;)
I came across this today System.Data.SqlTypes.SqlDateTime
it has
System.Data.SqlTypes.SqlDateTime.MinValue;
System.Data.SqlTypes.SqlDateTime.MaxValue;
among other methods & properties.
Convert hexadecimal\octal\binary string to decimal:
Convert.ToInt32("2A", 16); // equals 42
Convert.ToInt32("52", 8); // equals 42
Convert.ToInt32("101010", 2); // equals 42
A great way to convert numbers to byte array:
byte[] bytes = BitConverter.GetBytes(32767);
Or better, use Jon Skeet's MiscUtil for endian bit conversion.
Easy way of making an MD5 or SHA1 hash:
string hash = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile("string to hash", "MD5");
Quick way of generating a unique, temporary file on disk:
string tempFilePath = System.IO.Path.GetTempFileName();
The System.Web.VirtualPathUtility class also has some interesting methods for manipulating file paths.
Parse an enum into a string array in one line (eg. get all known colours from KnowColor enumeration into an array):
string[] colours = System.Enum.GetNames(typeof(System.Drawing.KnownColor));
If you want to annoy your server admin when he's at the console, add this to your web app :D
System.Media.SystemSounds.Exclamation.Play();
System.Security.SecurityElement.Escape
Escapes XML entities from a string so you can use it within an XML element. It's used by the framework in generation WS-Security XML, but saves four string replace statements in your own code.
I use these built-in delegate types (and their "overloaded" cousins) all the time:
Func<T, TResult>
Action<T>
Predicate<T>
Along with Lambdas is C# 3.0 they're pretty useful and can help make things more readable. (You can of course still use them with C# 2.0 and anonymous delegates).
System.IO.Path.Combine
Use this instead of concatenating the 2 strings yourself.
Use the
System.Diagnostics.Stopwatch
Don't do StartTime with DateTime, and then EndTime with DateTime.
See this answer.
I don't think it's a hidden feature, but I don't see it used often:
[System.Diagnostics.DebuggerStepThrough]
Quite useful when you have a pile of accessor-type functions or something which you don't want to be stepping into while debugging.
Here's one, inspired by Marcc's related Diagnostics attribute:
System.Diagnostics.DebuggerDisplay
It allows you to define the format of the string displayed in the Immediate / Locals window of Visual Studio, providing a string like "Person: {name} Cars: {cars.Count}" will display in the windows like "Person: John Doe Cars: 2".
My favorite hidden feature is the SDK. OK, not very hidden, for some people, but most people seem to be able to develop .NET applications only with a tool or IDE, like Visual Studio. The SDK is free, and for small applications it's way quicker for me to write them up in emacs and then just build them with the command line compilers, csc.exe or vbc.exe.
Plus all the SDK tools are handy, too. XML Schema Definition Tool (xsd.exe), Strong Name Tool (sn.exe), and many others.
TypeDescriptor when using Windows Forms data binding. This is how BindingSource can pretend to be any other object type.
I found several cases where people were not aware of certain properties of the Environment
class. In particular, I cleaned up several places in code and changed it to:
Environment.NewLine
(unit testing a templating engine that runs in Mono on *nix and .NET on Windows = HUGE improvement)Environment.CurrentDirectory
(replacedPath.GetFullPath('.')
throughout a file-manipulating utility)
String.Empty
seems to be a hidden feature for many developers. String.IsNullOrEmpty(string)
too.
The Managed, Native, and COM Interop Team at CodePlex have released a modified, open source TlbImp tool that allows simple creation of customized wrappers for pesky COM libraries.
If you have a custom MSBuild task in your project that processes a file and subsequently creates .cs
files to include in the same build, changes to the source file of the transformation often won't show in debugging without building twice. When you are generating a single file based solely on the content of a single source file, this task is best solved with a SingleFileGenerator. For multiple inputs and/or outputs, you may be stuck with an MSBuild task. In this case you can fix Visual Studio's dependency analysis by adding the following to your .csproj
file:
<PropertyGroup>
<UseHostCompilerIfAvailable>False</UseHostCompilerIfAvailable>
</PropertyGroup>
It's introduces a few other annoyances, but it will allow you to have deterministic, correct single builds (a rather important goal).
Microsoft.VisualBasic.IsNumeric(object)
Despite being in the Microsoft.VisualBasic.dll assembly, this method can be called by C# just as easily and can quickly let you know if the object being tested can be evaluated as a number.
Related to it are the various TryParse()
methods, which attempt to evaluate an object as a number but don't raise exceptions if the call fails... These can be found under a variety of different types such as System.Int32
and System.DateTime
If you're trying to convert between big/little endian then there is IPAddress.HostToNetworkOrder and IPAddress.NetworkToHostOrder. Why these methods were not part of the BitConverter class and in the obvious place people will look we'll never know.
[System.Diagnostics.ConditionalAttribute] - can be used instead of ugly preprocessor directives. For instance:
[Conditional("DEBUG")]
public void Validate()
{
// ...
}
I have to add Exception.GetBaseException(). I can't know how many times I've this code instead:
while(e.InnerException != null)
e = e.InnerException;
return e.Message;
instead of just:
return e.GetBaseException().Message;
The Action lambda is a delegate and hence gets the same delegate goodies that regular ones do - such as BeginInvoke():
new Action(() => MethodIWantToRunAsychronously())
.BeginInvoke(new AsyncCallback(x => ThingToDoWhenMethodReturns()), null);
What it does: Spawns a new thread and runs MethodIWantToRunAsychronously() on it while your continuing to execute the current method on the current thread. When MethodIWantToRunAsychronously completes, ThingToDoWhenMethodReturns() is called (still) on the new thread.
FormatterServices.GetUninitializedObject Activator.CreateInstance
Has someone mentioned above two?
Membership.GeneratePassword()
(msdn) will generate a secure temporary password for you.
ToString() method of Object base class is really nice thing. Override it then bring mouse over instance variable in debug time after instance variable created. Don't even need DebuggerDisplay
class Program
{
string name;
string surname;
static void Main(string[] args)
{
Program instance = new Program() { name = "James", surname = "hetfield" };
Console.ReadKey();
}
public override string ToString()
{
return string.Format("name is {0}, surname is {1}",name,surname);
}
}
string.Join([seperator], [array])
Couple this with LINQ and it rocks!
string.Join(",", customers.Select(c => c.Name).ToArray());
All your customer names in a CSV with one line of code :-)
System.Xml.XmlConvert contains lots of nice static methods to convert between XSD types and .Net types.