Two new Visual Studio snippets
I’ve been working on an interesting project recently and found that I needed two pieces of code a lot, so what better than wrapping them as snippets?
What are snippets?
Well, if you start typing in Visual Studio, you may see some options with a torn paper icon. If you select that and hit Tab (or hit Tab twice—once to select and once to invoke)—it will write code for you! These are contained in .snippet files, which are just XML files in a specific location.
To deploy these snippets, copy them to your C# custom snippets folder, which should be something like: C:\Users<Username>\Documents\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets
You can look at the end of this post for a sample of what the snippets create, but let’s have a quick overview of them.
Snippet 1: StructC
DOWNLOAD STRUCTC SNIPPET (Right-click → Save As)
Visual Studio already includes a snippet for creating a struct (which is also the snippet), but it is very basic:
StructC is a more complete implementation of a struct, mainly to comply with FxCop requirements. It includes:
- A
GetHashCodemethod - Both
Equalsmethods - The positive and negative equality operators (
==and!=) - Lots of comments
All of which adds up to 74 lines of code, rather than the three you’d get previously.
Warning – the GetHashCode uses reflection to determine a unique hash code, but this may not be ideal for all scenarios. Please review before use.
Snippet 2: Dispose
DOWNLOAD DISPOSE SNIPPET (Right-click → Save As)
If you’re implementing a class that needs to inherit IDisposable, you can use the option in Visual Studio to generate the methods.
Again, from an FxCop perspective, it’s lacking since you only get the Dispose method. Instead, you can use the dispose snippet, which generates 41 lines of code, including:
- A
#regionfor the code (same as if you used the VS option) - A properly implemented
Disposemethod that callsDispose(bool)andGC.SuppressFinalize - A
Dispose(bool)method for cleanup of managed and unmanaged objects - A private
boolvariable to ensureDisposeisn’t called multiple times
StructC Sample
/// <summary></summary>
struct MyStruct
{
//TODO: Add properties, fields, constructors etc...
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode()
{
int valueStorage = 0;
object objectValue = null;
foreach (PropertyInfo property in typeof(MyStruct).GetProperties())
{
objectValue = property.GetValue(this, null);
if (objectValue != null)
{
valueStorage += objectValue.GetHashCode();
}
}
return valueStorage;
}
/// <summary>
/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
/// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
if (!(obj is MyStruct))
return false;
return Equals((MyStruct)obj);
}
/// <summary>
/// Equalses the specified other.
/// </summary>
/// <param name="other">The other.</param>
/// <returns></returns>
public bool Equals(MyStruct other)
{
//TODO: Implement check to compare two instances of MyStruct
return true;
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="first">The first.</param>
/// <param name="second">The second.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(MyStruct first, MyStruct second)
{
return first.Equals(second);
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="first">The first.</param>
/// <param name="second">The second.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(MyStruct first, MyStruct second)
{
return !first.Equals(second);
}
}
Dispose Sample
#region IDisposable Members
/// <summary>
/// Internal variable which checks if Dispose has already been called.
/// </summary>
private bool disposed;
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
private void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
//TODO: Managed cleanup code here, while managed refs still valid.
}
//TODO: Unmanaged cleanup code here.
disposed = true;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
// Call the private Dispose(bool) helper and indicate that we are explicitly disposing.
this.Dispose(true);
// Tell the garbage collector that the object doesn’t require any cleanup when collected since Dispose was called explicitly.
GC.SuppressFinalize(this);
}
#endregion