In C#, how to determine if a class or an instance of the class implements an interface

I needed to determine if a class or one of its instances implements and interface. So I created this test project to see if this works.

Turns out it is really easy to do. Here is a test project that I used to learn. Just create a new console project and stick this code in the Program.cs and check it out.

namespace TestIfThisImplementsInterface
{
    class Program
    {
        static void Main(string[] args)
        {
            // Test if the type or its parent implements the interface
            bool bCarClass = typeof(IDrivable).IsAssignableFrom(typeof(Car));             // True
            bool bFordFocusClass = typeof(IDrivable).IsAssignableFrom(typeof(FordFocus)); // True
            bool bJunkerClass = typeof(IDrivable).IsAssignableFrom(typeof(Junker));       // False

            // Test if the exact type and not its parent implements the derived type
            bool bCarClassEx = typeof(Car).GetInterface(typeof(IDrivable).FullName) != null;           // True
            bool bFordFocusClassEx = typeof(Vehicle).GetInterface(typeof(IDrivable).FullName) != null; // False
            bool bJunkerClassEx = typeof(Junker).GetInterface(typeof(IDrivable).FullName) != null;     // True

            // Test if an instance implements or derivces from an oject that implements the interface
            bool bCarInstance = new Car() is IDrivable;             // True
            bool bFordFocusInstance = new FordFocus() is IDrivable; // True
            bool bJunkerInstance = new Junker() is IDrivable;       // False

            // Test if an instance implements or derivces from an oject that implements the interface
            bool bCarInstanceEx = new Car().GetType().GetInterface(typeof(IDrivable).FullName) != null;             // True
            bool bFordFocusInstanceEx = new FordFocus().GetType().GetInterface(typeof(IDrivable).FullName) != null; // False
            bool bJunkerInstanceEx = new Junker().GetType().GetInterface(typeof(IDrivable).FullName) != null;       // False

            // Show that the test can be in the parent class but the actual class is what is tested
            // This is actually what I needed. Glad it worked!
            bool bCarParentFunction = new Car().IsDrivable;             // True
            bool bFordFocusParentFunction = new FordFocus().IsDrivable; // True
            bool bJunkerParentFunction = new Junker().IsDrivable;       // False
        }
    }

    public interface IDrivable
    {
        void Drive();
    }

    public class Vehicle
    {
        public virtual bool IsDrivable
        {
            get { return this is IDrivable; }
        }
    }

    public class Car : Vehicle, IDrivable
    {
        #region IDrivable Members
        public void Drive()
        {
            // Drive code here
        }
        #endregion
    }

    public class FordFocus : Car
    {
    }

    public class Junker : Vehicle
    {
    }
}

Resource:
http://www.hanselman.com/blog/DoesATypeImplementAnInterface.aspx

How to authenticate and access the registry remotely using C#

Connecting to the remote registry of another workstation or server can be done as long as authentication has been done first.

Here is an example for connecting to remote registry.

  1. Create a new C# Console project in Visual Studio.
  2. Add a new class called NetworkShare. I know I got this from another site sometime last year and added to it, but I didn’t document the source web site.
    using System;
    using System.Runtime.InteropServices;
    
    using BOOL = System.Int32;
    
    namespace NetworkConnection
    {
        public class NetworkShare
        {
            #region Member Variables
            [DllImport("mpr.dll")]
            private static extern int WNetAddConnection2A(ref NetResource refNetResource, string inPassword, string inUsername, int inFlags);
            [DllImport("mpr.dll")]
            private static extern int WNetCancelConnection2A(string inServer, int inFlags, int inForce);
    
            private String _Server;
            private String _Share;
            private String _DriveLetter = null;
            private String _Username = null;
            private String _Password = null;
            private int _Flags = 0;
            private NetResource _NetResource = new NetResource();
            BOOL _AllowDisconnectWhenInUse = 0; // 0 = False; Any other value is True;
            #endregion
    
            #region Constructors
            /// <summary>
            /// The default constructor
            /// </summary>
            public NetworkShare()
            {
            }
    
            /// <summary>
            /// This constructor takes a server and a share.
            /// </summary>
            public NetworkShare(String inServer, String inShare)
            {
                _Server = inServer;
                _Share = inShare;
            }
    
            /// <summary>
            /// This constructor takes a server and a share and a local drive letter.
            /// </summary>
            public NetworkShare(String inServer, String inShare, String inDriveLetter)
            {
                _Server = inServer;
                _Share = inShare;
                DriveLetter = inDriveLetter;
            }
    
            /// <summary>
            /// This constructor takes a server, share, username, and password.
            /// </summary>
            public NetworkShare(String inServer, String inShare, String inUsername, String inPassword)
            {
                _Server = inServer;
                _Share = inShare;
                _Username = inUsername;
                _Password = inPassword;
            }
    
            /// <summary>
            /// This constructor takes a server, share, drive letter, username, and password.
            /// </summary>
            public NetworkShare(String inServer, String inShare, String inDriveLetter, String inUsername, String inPassword)
            {
                _Server = inServer;
                _Share = inShare;
                _DriveLetter = inDriveLetter;
                _Username = inUsername;
                _Password = inPassword;
            }
            #endregion
    
            #region Properties
            public String Server
            {
                get { return _Server; }
                set { _Server = value; }
            }
    
            public String Share
            {
                get { return _Share; }
                set { _Share = value; }
            }
    
            public String FullPath
            {
                get { return string.Format(@"\\{0}\{1}", _Server, _Share); }
            }
    
            public String DriveLetter
            {
                get { return _DriveLetter; }
                set { SetDriveLetter(value); }
            }
    
            public String Username
            {
                get { return String.IsNullOrEmpty(_Username) ? null : _Username; }
                set { _Username = value; }
            }
    
            public String Password
            {
                get { return String.IsNullOrEmpty(_Password) ? null : _Username; }
                set { _Password = value; }
            }
    
            public int Flags
            {
                get { return _Flags; }
                set { _Flags = value; }
            }
    
            public NetResource Resource
            {
                get { return _NetResource; }
                set { _NetResource = value; }
            }
    
            public bool AllowDisconnectWhenInUse
            {
                get { return Convert.ToBoolean(_AllowDisconnectWhenInUse); }
                set { _AllowDisconnectWhenInUse = Convert.ToInt32(value); }
            }
    
            #endregion
    
            #region Functions
            /// <summary>
            /// Establishes a connection to the share.
            ///
            /// Throws:
            ///
            ///
            /// </summary>
            public int Connect()
            {
                _NetResource.Scope = (int)Scope.RESOURCE_GLOBALNET;
                _NetResource.Type = (int)Type.RESOURCETYPE_DISK;
                _NetResource.DisplayType = (int)DisplayType.RESOURCEDISPLAYTYPE_SHARE;
                _NetResource.Usage = (int)Usage.RESOURCEUSAGE_CONNECTABLE;
                _NetResource.RemoteName = FullPath;
                _NetResource.LocalName = DriveLetter;
    
                return WNetAddConnection2A(ref _NetResource, _Password, _Username, _Flags);
            }
    
            /// <summary>
            /// Disconnects from the share.
            /// </summary>
            public int Disconnect()
            {
                int retVal = 0;
                if (null != _DriveLetter)
                {
                    retVal = WNetCancelConnection2A(_DriveLetter, _Flags, _AllowDisconnectWhenInUse);
                    retVal = WNetCancelConnection2A(FullPath, _Flags, _AllowDisconnectWhenInUse);
                }
                else
                {
                    retVal = WNetCancelConnection2A(FullPath, _Flags, _AllowDisconnectWhenInUse);
                }
                return retVal;
            }
    
            private void SetDriveLetter(String inString)
            {
                if (inString.Length == 1)
                {
                    if (char.IsLetter(inString.ToCharArray()[0]))
                    {
                        _DriveLetter = inString + ":";
                    }
                    else
                    {
                        // The character is not a drive letter
                        _DriveLetter = null;
                    }
                }
                else if (inString.Length == 2)
                {
                    char[] drive = inString.ToCharArray();
                    if (char.IsLetter(drive[0]) && drive[1] == ':')
                    {
                        _DriveLetter = inString;
                    }
                    else
                    {
                        // The character is not a drive letter
                        _DriveLetter = null;
                    }
                }
                else
                {
                    // If we get here the value passed in is not valid
                    // so make it null.
                    _DriveLetter = null;
                }
            }
            #endregion
    
            #region NetResource Struct
            [StructLayout(LayoutKind.Sequential)]
            public struct NetResource
            {
                public uint Scope;
                public uint Type;
                public uint DisplayType;
                public uint Usage;
                public string LocalName;
                public string RemoteName;
                public string Comment;
                public string Provider;
            }
            #endregion
    
            #region Enums
            public enum Scope
            {
                RESOURCE_CONNECTED = 1,
                RESOURCE_GLOBALNET,
                RESOURCE_REMEMBERED,
                RESOURCE_RECENT,
                RESOURCE_CONTEXT
            }
    
            public enum Type : uint
            {
                RESOURCETYPE_ANY,
                RESOURCETYPE_DISK,
                RESOURCETYPE_PRINT,
                RESOURCETYPE_RESERVED = 8,
                RESOURCETYPE_UNKNOWN = 4294967295
            }
    
            public enum DisplayType
            {
                RESOURCEDISPLAYTYPE_GENERIC,
                RESOURCEDISPLAYTYPE_DOMAIN,
                RESOURCEDISPLAYTYPE_SERVER,
                RESOURCEDISPLAYTYPE_SHARE,
                RESOURCEDISPLAYTYPE_FILE,
                RESOURCEDISPLAYTYPE_GROUP,
                RESOURCEDISPLAYTYPE_NETWORK,
                RESOURCEDISPLAYTYPE_ROOT,
                RESOURCEDISPLAYTYPE_SHAREADMIN,
                RESOURCEDISPLAYTYPE_DIRECTORY,
                RESOURCEDISPLAYTYPE_TREE,
                RESOURCEDISPLAYTYPE_NDSCONTAINER
            }
    
            public enum Usage : uint
            {
                RESOURCEUSAGE_CONNECTABLE = 1,
                RESOURCEUSAGE_CONTAINER = 2,
                RESOURCEUSAGE_NOLOCALDEVICE = 4,
                RESOURCEUSAGE_SIBLING = 8,
                RESOURCEUSAGE_ATTACHED = 16,
                RESOURCEUSAGE_ALL = 31,
                RESOURCEUSAGE_RESERVED = 2147483648
            }
    
            public enum ConnectionFlags : uint
            {
                CONNECT_UPDATE_PROFILE = 1,
                CONNECT_UPDATE_RECENT = 2,
                CONNECT_TEMPORARY = 4,
                CONNECT_INTERACTIVE = 8,
                CONNECT_PROMPT = 16,
                CONNECT_NEED_DRIVE = 32,
                CONNECT_REFCOUNT = 64,
                CONNECT_REDIRECT = 128,
                CONNECT_LOCALDRIVE = 256,
                CONNECT_CURRENT_MEDIA = 512,
                CONNECT_DEFERRED = 1024,
                CONNECT_COMMANDLINE = 2048,
                CONNECT_CMD_SAVECRED = 4096,
                CONNECT_CRED_RESET = 8192,
                CONNECT_RESERVED = 4278190080
            }
            #endregion
        }
    }
    

    Note: This class actually is to map a drive, but authenticating to a share and authenticating to connect to remote registry are done the same way.

  3. Now here is a Program.cs that shows how to use the NetworkShare class to connect to a device and access the remote registry.
    using System;
    using Microsoft.Win32;
    using NetworkConnection;
    using System.Management;
    
    namespace RemoteRegistryExample
    {
        class Program
        {
            static void Main(string[] args)
            {
                String ServerName = "Server1";
    
                // Create an object that can authenticate to a network share when you
                // already have credentials
                NetworkShare share = new NetworkShare(ServerName, "ipc$");
    
                // Create an object that can authenticate to a network share when you
                // do NOT already have credentials
                //NetworkShare share = new NetworkShare(ServerName, "C$", "User", "SomePasswd");
    
                // Connect to the remote drive
                share.Connect();
    
                // Note: another connection option is to add a reference to System.Management,
                // Then add a using statement for System.Management and use ConnectionOptions
                // and ManagementScope objects. For more information see this link:
                // http://msdn.microsoft.com/en-us/library/system.management.managementscope%28v=VS.100%29.aspx
    
                // If these same credentials allow remote registry, you are now authenticated
                // Get the Windows ProductName from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
                String ProductName = string.Empty;
                RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ServerName);
                if (key != null)
                {
                    key = key.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
                    if (key != null)
                        ProductName = key.GetValue("ProductName").ToString();
                }
    
                // Display the value
                Console.WriteLine("The device " + ServerName + " is running " + ProductName + ".");
    
                // Disconnect the share
                share.Disconnect();
            }
        }
    }
    

    You now are reading from remote registry.

Loading rich text file links in a browser from a WPF Navigation Application

Previously, I discussed loading a rich text file in a regular WPF Application in this post:
Loading a RichTextBox from an RTF file using binding or a RichTextFile control

The following use cases must be met:

  1. Load and display a rich text file in read only mode
  2. The links must open inside a browser and not in the application

We created a RichTextFile control that inherits RichTextBox and configured it to support binding. Now we are going to use this same object in a WPF Navigation Application.

A WPF Navigation Application is going to react differently. Links are going work by default, so the Hyperlink.Click event doesn’t have to be used. However, there is a problem, the links open in the actual application’s window and not in a browser. Lets fix this.

Part 2 – Using the RichTextFile class in a WPF Navigation Application

Use Case 1 – Loading a rich text file

Create a new WPF Application in Visual Studio.

Add a Frame element and set the source to RTF.xaml, which we will create next.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame Source="RTF.xaml" />
    </Grid>
</Window>

There is no code behind for this, yet.

Create a new WPF Page called RTF.xaml.

Add the above RichTextFile object to the project.

Add an xmlns reference to our new object. Then add our new object. Notice in our new object that we set IsReadOnly=”True” but we also set IsDocumentEnabled=”True”. This allows for clicking a link even though the document is read only.

<Page x:Class="RichTextFileTest.RTF"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="RTF"
      xmlns:controls="clr-namespace:System.Windows.Controls">
    <Grid>
        <controls:RichTextFile File="{Binding File}" IsReadOnly="True" IsDocumentEnabled="True"/>
    </Grid>
</Page>

Code Behind

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace RichTextFileTest
{
    /// <summary>
    /// Interaction logic for RTF.xaml
    /// </summary>
    public partial class RTF : Page
    {
        public RTF()
        {
            InitializeComponent();
            Example example = new Example() { File = "File.rtf" };
            DataContext = example;
        }
    }

    public class Example
    {
        public String File { get; set; }
    }
}

Now the first use case is complete, the rich text file is loading into the RichTextFile control and is visible in the application. However, the second use case is incomplete, but not because the links aren’t loading, but because they are not loading in a browser. Instead they are loading inside the Frame element.

Use Case 2 – Getting the links to open in a browser

Getting the links to open in a browser is not straight forward and it took me quite some time to find an easy solution. Somehow, the link must be open in a browser and then the Navigation event must be canceled.

The easiest way to do this is to implement the Nagivating function on the Frame element in our MainWindow.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame Source="RTF.xaml" Navigating="Frame_Navigating"/>
    </Grid>
</Window>

Now implement the code behind for the Frame_Navigating method.

using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace RichTextFileTest
{
    /// <summary> 
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Frame_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            Frame frame = sender as Frame;
            if (frame != null && frame.Source != null)
            {
                // See if we are hitting a link using HTTP or HTTPS
                if (frame.Source.ToString().StartsWith("http://", System.StringComparison.CurrentCultureIgnoreCase)
                    || frame.Source.ToString().StartsWith("https://", System.StringComparison.CurrentCultureIgnoreCase))
                {
                    // Open the URL in a browser
                    Process.Start(frame.Source.ToString());

                    // Cancel the Navigation event
                    e.Cancel = true;
                }
            }
        }
    }
}

The links should now be opening in your browser and not in your application.

Here is the sample project that demonstrates this.
RichTextFileNavigation.zip

Loading a RichTextBox from an RTF file using binding or a RichTextFile control

Sometimes you have a rich text document that exists as an actual file and you simply want to load the file and display it.

My exact use cases are these:

  1. Load and display a rich text file in read only mode
  2. The links must open inside a browser and not in the application

I like to use MVVM, so my goal is to use binding to pass in the file name. Unfortunately the RichTextBox class is not designed to bind to a file name. However, extending this control to have this functionality is quite easy.

RichTextFile extending RichTextBox

Here is my new class. I have extended RichTextBox with four additional items in a new derived class called RichTextFile.

  1. Added a String Property called File.
  2. Added a DependecyProperty called FileProperty
  3. Added a PropertyChangedCallback function called OnFileChanged
  4. Added a ReadFile function that reads a .rtf file into a FlowDocument

RichTextFile.cs

using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace System.Windows.Controls
{
    class RichTextFile : RichTextBox
    {
        #region Properties
        public String File
        {
            get { return (String)GetValue(FileProperty); }
            set { SetValue(FileProperty, value); }
        }

        public static DependencyProperty FileProperty =
            DependencyProperty.Register("File", typeof(String), typeof(RichTextFile),
            new PropertyMetadata(new PropertyChangedCallback(OnFileChanged)));

        private static void OnFileChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextFile rtf = d as RichTextFile;
            if (d == null)
                return;

            ReadFile(rtf.File, rtf.Document);
        }
        #endregion

        #region Functions
        private static void ReadFile(string inFilename, FlowDocument inFlowDocument)
        {
            if (System.IO.File.Exists(inFilename))
            {
                TextRange range = new TextRange(inFlowDocument.ContentStart, inFlowDocument.ContentEnd);
                FileStream fStream = new FileStream(inFilename, FileMode.Open, FileAccess.Read, FileShare.Read);

                range.Load(fStream, DataFormats.Rtf);
                fStream.Close();
            }
        }
        #endregion
    }
}

You can use this new object to load a .rtf file quite easily. I am going to show you how I succeeding in my two use cases using both a regular WPF Application and a WPF Navigation Application.

Part 1 – Using the RichTextFile class in a WPF Application

Use Case 1 – Loading a rich text file

Create a new WPF Application in Visual Studio.

Add the above RichTextFile object to the project.

Add an xmlns reference to our new object. Then add our new object. Notice in our new object that we set IsReadOnly=”True” but we also set IsDocumentEnabled=”True”. This allows for clicking a link even though the document is read only.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:controls="clr-namespace:System.Windows.Controls">
    <Grid>
        <controls:RichTextFile File="{Binding File}" IsReadOnly="True" IsDocumentEnabled="True" />
    </Grid>
</Window>

Code Behind

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Documents;

namespace RichTextFileTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Example example = new Example() { File = "File.rtf" };
            DataContext = example;
        }
    }

    public class Example
    {
        public String File { get; set; }
    }
}

Now the first use case is complete, the rich text file is loading into the RichTextFile control and is visible in the application. However, the second use case is incomplete as clicking the link does nothing.

Use Case 2 – Getting the links to open in a browser

The links can easily made to open in a browser by implementing the Hyperlink.Click event on the RichTextFile. Here is how this is done.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:controls="clr-namespace:System.Windows.Controls">
    <Grid>
        <controls:RichTextFile File="{Binding File}" IsEnabled="True" IsReadOnly="True" IsDocumentEnabled="True" Hyperlink.Click="RichTextFile_Click"/>
    </Grid>
</Window>

Then define the event function in the code behind.

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Documents;

namespace RichTextFileTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Example example = new Example() { File = "File.rtf" };
            DataContext = example;
        }

        private void RichTextFile_Click(object sender, RoutedEventArgs e)
        {
            Hyperlink link = e.OriginalSource as Hyperlink;
            if (link != null)
            {
                Process.Start(link.NavigateUri.ToString());
            }
        }
    }

    public class Example
    {
        public String File { get; set; }
    }
}

The links should now be opening in your browser.

Here is the sample project that demonstrates this.
RichTextFileTest.zip

Part 2 – Using the RichTextFile class in a WPF Navigation Application

Some sample extension methods for the string class

Because String is a sealed class you cannot inherit from it and add to it. However, C# has a wonderful feature called extension methods.

Extension methods enable you to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type. [1]

Here is a list of extension methods I have used for the String class.

If you know of any more cool extension methods, please comment.

using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Security;

namespace LANDesk.Install.Common.Extenders
{
    /// <summary>
    /// This class adds methods to String that are useful
    /// </summary>
    public static class StringExtender
    {
        #region DLL Imports
        [DllImport("ldmsinst.dll", CharSet = CharSet.Ansi, EntryPoint = "Decrypt", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Decrypt(int pwdLen, byte[] pwd);

        [DllImport("ldmsinst.dll", CharSet = CharSet.Ansi, EntryPoint = "Encrypt", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Encrypt(int length, byte[] data);
        #endregion

        /// <summary>
        /// This adds a function to a string object that will convert the string
        /// to a SecureString.
        /// </summary>
        /// <param name="password">The string to convert to a secure string.</param>
        /// <returns>SecureString</returns>
        public static SecureString ConvertToSecureString(this string password)
        {
            SecureString ss = new SecureString();
            if (password == null)
                throw new ArgumentNullException("password");

            foreach (Char c in password)
            {
                ss.AppendChar(c);
            }
            return ss;
        }

        /// <summary>
        /// Checks if the string contains any of a list of characters
        /// entered as a string.
        /// </summary>
        /// <param name="password">Any string.</param>
        /// <param name="listofcharacters">Any string representing a list of characters.</param>
        /// <returns>bool</returns>
        public static bool ContainsAnyOf(this string password, char[] listofcharacters)
        {
            foreach (char c in listofcharacters)
            {
                if (password.Contains(c.ToString()))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Checks if the string contains any of a list of characters
        /// entered as a string.
        /// </summary>
        /// <param name="password">Any string.</param>
        /// <param name="listofcharacters">Any string representing a list of characters.</param>
        /// <returns>bool</returns>
        public static bool ContainsAnyOf(this string password, string listofcharacters)
        {
            return password.ContainsAnyOf(listofcharacters.ToCharArray());
        }

        /// <summary>
        /// Checks if the string has a space.
        /// </summary>
        /// <param name="txt">Any string.</param>
        /// <returns>bool</returns>
        public static bool HasSpaces(string txt)
        {
            if (txt.Contains(" "))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// To be a strong password, Must have 3 out of 4 of the following conditions:
        /// Uppercase, lowercase, numberic, symbol
        /// </summary>
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static bool IsPasswordStrong(this string password)
        {
            int numTypes = 0;

            if (HasUppercaseCharacter(password) == true)
            {
                numTypes = numTypes + 1;
            }
            if (HasLowercaseCharacter(password) == true)
            {
                numTypes = numTypes + 1;
            }
            if (HasNonAlphaNumeric(password) == true)
            {
                numTypes = numTypes + 1;
            }
            if (HasDigit(password) == true)
            {
                numTypes = numTypes + 1;
            }

            if (numTypes > 2)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool HasUppercaseCharacter(string str)
        {
            if (str == str.ToLower())
                return false;
            return true;
        }

        public static bool HasLowercaseCharacter(string str)
        {
            if (str == str.ToUpper())
                return false;
            return true;
        }

        public static bool HasDigit(string str)
        {
            Regex regexNums = new Regex("[0-9]");
            return regexNums.IsMatch(str);
        }

        public static bool HasNonAlphaNumeric(string str)
        {
            string newString = str;

            Regex regexNums = new Regex("[0-9]");
            Regex regexAlphas = new Regex("[a-z]", RegexOptions.IgnoreCase);

            newString = regexNums.Replace(newString, "");
            newString = regexAlphas.Replace(newString, "");

            return (newString.Length > 0);
        }

        /// <summary>
        /// This adds a function to a string object that RC4 Encrypts a password.
        /// </summary>
        /// <param name="password">A password as a string.</param>
        /// <returns>A byte[] representation of an RC4 password.</returns>
        public static byte[] Encrypt(this string password)
        {
            try
            {
                // Encode the password
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                byte[] encryptedPwd = encoding.GetBytes(password);

                // encrypt password
                Encrypt(encryptedPwd.Length, encryptedPwd);
                return encryptedPwd;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// This adds a function to a byte[] object that decrypts an RC4 password.
        /// and returns the password as a string.
        /// </summary>
        /// <param name="encryptedPwd">A byte[] representation of an RC4 password.</param>
        /// <returns>The password as a string.</returns>
        static public string Decrypt(this byte[] encryptedPwd)
        {
            string password = string.Empty;
            try
            {
                    // decrypt password
                    Decrypt(encryptedPwd.Length, encryptedPwd);

                    // convert from byte array to string
                    password = System.Text.ASCIIEncoding.Default.GetString(encryptedPwd);
                    password = password.Replace("\0", string.Empty);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return password;
        }

        public static string FirstLetterUpperCase(this string inString)
        {
            if (string.IsNullOrEmpty(inString))
                return string.Empty;

            string newString = inString.Substring(0, 1).ToUpper();
            newString += inString.Substring(1, inString.Length - 1);
            return newString;
        }

        public static string LimitTo(this string data, int length)
        {
            return data.Length < length ? data : data.Substring(0, length);
        }
    }
}

How to have the TextBlock in a left column of a Grid in a ListView Template expand or shrink with text wrapping?

Ok, lets say you want to have a Grid where each item is a row of data in a Grid. The left most column should expand or shrink, and yes the text should wrap when it shrinks.

Not so easy…but it can be done if you use the right tools.

  • Use a DockPanel not a Grid
  • Make the left most column the last one added
<Window x:Class="ListBoxWithWrap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        d:DesignHeight="242"
        d:DesignWidth="388"
        >
    <Grid>
        <DockPanel Name="MainGrid" HorizontalAlignment="Stretch">
            <!-- These four blocks will have other content eventually, but only need to be 45 wide -->
            <TextBlock Text="X" Grid.Column="1" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <TextBlock Text="X" Grid.Column="2" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <TextBlock Text="X" Grid.Column="3" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <TextBlock Text="X" Grid.Column="4" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <!-- This is the TextBlock that needs to wrap its content (and
                             change the height of the row (so the full content is still
                             visible) to whatever the available space is, but should not
                             make overall ListView wider than the parent's width. -->
            <TextBlock Text="A very long string that should wrap when the window is small." Padding="20,6,6,6" TextWrapping="Wrap" DockPanel.Dock="Right"/>
        </DockPanel>
    </Grid>
</Window>

You will see that this works as you desire.

Now put this in a ListView’s Template and set it to use Binding.

<Window x:Class="ListBoxWithWrap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        mc:Ignorable="d"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        d:DesignHeight="242"
        d:DesignWidth="388"
        SizeToContent="WidthAndHeight">
    <Grid>
        <ListView Name="lvWrap" ItemsSource="{Binding}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <DockPanel Name="MainGrid" HorizontalAlignment="Stretch">
                        <!-- These four blocks will have other content eventually, but only need to be 45 wide -->
                        <TextBlock Text="X" Grid.Column="1" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="2" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="3" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="4" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <!-- This is the TextBlock that needs to wrap its content (and
                             change the height of the row (so the full content is still
                             visible) to whatever the available space is, but should not
                             make overall ListView wider than the parent's width. -->
                        <TextBlock Text="{Binding Content}" Padding="20,6,6,6" TextWrapping="Wrap" DockPanel.Dock="Right"/>
                    </DockPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

Now give it some data to bind to.

using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;

namespace ListBoxWithWrap
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            List<SomeItem> list = new List<SomeItem>();
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });

            lvWrap.DataContext = list;
        }

        public class SomeItem
        {
            public string Content { get; set; }
        }
    }
}

The shrink with text wrapping no longer works once inside of the ListView. So that tells you that something to do with the ListView is breaking the feature you want.

Here is how you fix this:

1. Open your project in Expression Blend. (If you don’t have Expression Blend, maybe just look at my code below and copy it)

2. Right-Click on the ListView in the Object and Timeline tab and choose Edit Template | Edit a Copy.

3. Click OK on the next Window.

This will create the following resource code.

<Window.Resources>
		<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
		<Style x:Key="ListViewStyle1" TargetType="{x:Type ListView}">
			<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
			<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
			<Setter Property="BorderThickness" Value="1"/>
			<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
			<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
			<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
			<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
			<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
			<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
			<Setter Property="VerticalContentAlignment" Value="Center"/>
			<Setter Property="Template">
				<Setter.Value>
					<ControlTemplate TargetType="{x:Type ListView}">
						<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
							<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
								<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
							</ScrollViewer>
						</Border>
						<ControlTemplate.Triggers>
							<Trigger Property="IsEnabled" Value="false">
								<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
							</Trigger>
							<Trigger Property="IsGrouping" Value="true">
								<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
							</Trigger>
						</ControlTemplate.Triggers>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
		</Style>
	</Window.Resources>

4. Now look at what is surrounding the ItemPresenter. Yes, you see the ScrollViewer, which is your problem. Delete it.

5. Build you project.

Success! Now your feature to both expand or shrink with text wrapping is back.

Here is the final XAML.

<Window x:Class="ListBoxWithWrap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        mc:Ignorable="d"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        d:DesignHeight="242"
        d:DesignWidth="388"
        SizeToContent="WidthAndHeight">
    <Window.Resources>
        <SolidColorBrush x:Key="ListBorder" Color="#828790"/>
        <Style x:Key="ListViewStyle1" TargetType="{x:Type ListView}">
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
            <Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
            <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
            <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListView}">
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                            </Trigger>
                            <Trigger Property="IsGrouping" Value="true">
                                <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <ListView Name="lvWrap" ItemsSource="{Binding}" Style="{DynamicResource ListViewStyle1}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <DockPanel Name="MainGrid" HorizontalAlignment="Stretch">
                        <!-- These four blocks will have other content eventually, but only need to be 45 wide -->
                        <TextBlock Text="X" Grid.Column="1" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="2" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="3" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="4" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <!-- This is the TextBlock that needs to wrap its content (and
                             change the height of the row (so the full content is still
                             visible) to whatever the available space is, but should not
                             make overall ListView wider than the parent's width. -->
                        <TextBlock Text="{Binding Content}" Padding="20,6,6,6" TextWrapping="Wrap" DockPanel.Dock="Right"/>
                    </DockPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

You should now have a little bit more understanding of the ListView template and how to manipulate it, which should translate to other objects in WPF as well.

Options for copying a directory recursively with C#

Today I had the task of copying a directory recursively in C#. The first thing I did was type into my project “Directory.” and see if intellisense brought up a function called Directory.Copy. Unfortunately there is not a Directory.Copy, which to me seems like an oversight, as copying a directory is fairly common. Maybe it is not an action commonly done in C#.

So next I went to my browser and did a search. Well, I am not the first, nor will I be the last to solve this. There are a number of solutions online and each seem to have both positive and negative comments.

Option 1 – A directory copy using recursion

Pros: This is simple and to the point and elegant.

Cons: One complaint is that this could cause a stack overly by using recursion but this might not be a valid con as the filesystem restrictions in Windows might prevent a stack overflow anyway.

Since I am dealing with a small controlled tree, the con will not affect me., but since we are dealing with a file system, this is likely not to occur.

        private static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
        {
            foreach (DirectoryInfo dir in source.GetDirectories())
                CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
            foreach (FileInfo file in source.GetFiles())
                file.CopyTo(Path.Combine(target.FullName, file.Name));
        }

Option 2 – Use SearchOption.AllDirectories to create the directory structure then then copy all the files

Pros: Does not use recursion
Cons: Are there any?

        private static void CopyFilesRecursively(String SourcePath, String DestinationPath)
        {
            // First create all of the directories
            foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
                Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));

            // Copy all the files
            foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
                File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath));
        }

Option 3 – Use one of the methods recommended by MSDN

Unfortunately MSDN is not consistent, and recommends two different methods in two different places, which I am sure were written by different teams.

using System;
using System.IO;

class DirectoryCopyExample
{
    static void Main()
    {
        DirectoryCopy(".", @".\temp", true);
    }

    private static void DirectoryCopy(
        string sourceDirName, string destDirName, bool copySubDirs)
    {
      DirectoryInfo dir = new DirectoryInfo(sourceDirName);
      DirectoryInfo[] dirs = dir.GetDirectories();

      // If the source directory does not exist, throw an exception.
        if (!dir.Exists)
        {
            throw new DirectoryNotFoundException(
                "Source directory does not exist or could not be found: "
                + sourceDirName);
        }

        // If the destination directory does not exist, create it.
        if (!Directory.Exists(destDirName))
        {
            Directory.CreateDirectory(destDirName);
        }

        // Get the file contents of the directory to copy.
        FileInfo[] files = dir.GetFiles();

        foreach (FileInfo file in files)
        {
            // Create the path to the new copy of the file.
            string temppath = Path.Combine(destDirName, file.Name);

            // Copy the file.
            file.CopyTo(temppath, false);
        }

        // If copySubDirs is true, copy the subdirectories.
        if (copySubDirs)
        {

            foreach (DirectoryInfo subdir in dirs)
            {
                // Create the subdirectory.
                string temppath = Path.Combine(destDirName, subdir.Name);

                // Copy the subdirectories.
                DirectoryCopy(subdir.FullName, temppath, copySubDirs);
            }
        }
    }
}

Or the different one they posted here:

using System;
using System.IO;

class CopyDir
{
    public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
    {
        if (source.FullName.ToLower() == target.FullName.ToLower())
        {
            return;
        }

        // Check if the target directory exists, if not, create it.
        if (Directory.Exists(target.FullName) == false)
        {
            Directory.CreateDirectory(target.FullName);
        }

        // Copy each file into it's new directory.
        foreach (FileInfo fi in source.GetFiles())
        {
            Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
            fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
        }

        // Copy each subdirectory using recursion.
        foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
        {
            DirectoryInfo nextTargetSubDir =
                target.CreateSubdirectory(diSourceSubDir.Name);
            CopyAll(diSourceSubDir, nextTargetSubDir);
        }
    }

    public static void Main()
    {
        string sourceDirectory = @"c:\sourceDirectory";
        string targetDirectory = @"c:\targetDirectory";

        DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
        DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);

        CopyAll(diSource, diTarget);
    }

    // Output will vary based on the contents of the source directory.
}

Option 4 – Use Microsoft.VisualBasic

Pros: One line.
Cons: You have to reference an additional dll that you otherwise do not need.
This additional dll is not available in Mono for cross-platform development.

new Microsoft.VisualBasic.Devices.Computer().
    FileSystem.CopyDirectory( sourceFolder, outputFolder );

There are various other methods:

Resources:
http://stackoverflow.com/questions/58744/best-way-to-copy-the-entire-contents-of-a-directory-in-c
http://msdn.microsoft.com/en-us/library/system.io.directoryinfo.aspx
http://msdn.microsoft.com/en-us/library/bb762914.aspx
http://xneuron.wordpress.com/2007/04/12/copy-directory-and-its-content-to-another-directory-in-c/
http://www.logiclabz.com/c/copy-directory-in-net-c-including-sub-folders.aspx

A quick overview of MVVM

Model View ViewModel (MVVM) is a design pattern based on Model View Controller (MVC) but specifically tailored to Windows Presentation Foundation (WPF).

MVVM is not a framework per se but many frameworks have been created. Here is a list of MVVM Frameworks from Wikipedia.

See the Wikipedia site here: Open Source MVVM Frameworks.

Another blog, has some basic information on many of these here: A quick tour of existing MVVM frameworks

A framework is actually not necessary to implement MVVM and you should seriously consider whether using one is right for your WPF application or not. Many applications do not need much of the features the frameworks provide. However, there are two common classes that all MVVM frameworks contain. These are ViewModelBase and RelayCommand. Though some frameworks may give them different names or implement them slightly differently, they all have these classes. For example, MVVM Foundation names the ViewModelBase differently. It is called ObservableObject, which is more appropriate because it is incorrect to assume that all objects that implement INotifyPropertyChanged are going to be ViewModel objects.

Instead of installing and using an MVVM framework, you could simply include these classes in your application, as these are all you need to implement MVVM.

  • ObservableObject
  • RelayCommand

While these two classes are enough, you may want to investigate how different MVVM Frameworks implement and what else they implement and why. You may find that another feature implemented is exactly what you need in your application and knowing about it could save you time.

The Array class in C#

System.Array is an important class to know and understand as almost any programming work has arrays.

Array is an abstract class, so you cannot establish and instance of it. That is OK because it is really just a “function holder” class. The term “function holder” is not an official C# term, but it is a name I give classes that really just exist to hold functions. Array is a “function holder” for array functions.

Lets take a moment to learn a few of the functions in the Array class. We are going to use an array of high scores to learn from.

Array.Sort

Let start by creating an array of high scores. The following code has a function that takes a score and adds it to the list if it is greater than the lowest high score and sorting them.

using System;

namespace ArrayLearning
{
    class Program
    {
        static int[] highScores = new int[12];

        static void Main(string[] args)
        {
            // keep that top 12 high scores
            AddScore(10100);
            AddScore(13710);
            AddScore(14190);
            AddScore(12130);
            AddScore(12130);
            AddScore(16140);
            AddScore(19320);
            AddScore(07250);
            AddScore(18140);
            AddScore(08090);
            AddScore(10010);
            AddScore(14380);
            AddScore(18140);
            AddScore(12190);
            AddScore(19320);
        }

        static void AddScore(int newScore)
        {
            // Pre-sort the high scores in case somehow the
            // first one is not the lowest.
            Array.Sort(highScores);

            // If the new score is greater than the lowest
            // high score, replace the lowest high score
            if (highScores[0] < newScore)
                highScores[0] = newScore;

            // Now resort the scores as the new score may
            // not be in the right place
            Array.Sort(highScores);

            DisplayHighScores();
        }

        private static void DisplayHighScores()
        {
            // Print the new high scores
            for (int i = highScores.Length - 1; i > -1; i--)
            {
                Console.WriteLine(highScores[i]);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
            Console.WriteLine();
        }
    }
}

Ok, I am not saying this is the proper way to handle high scores in a game. I am just demonstrating Array.Sort for you.

Array.Clear

Ok, lets show an example of Array.Clear. This is a very simple function that sets all the values in the array to their default value. Booleans have a default value of false. Double, Int32, Int64, etc, have a default value of 0. Reference types have a default value of null.

Here is an enhancement to the above snippet that allows demonstrates clearing an entire array. Notice Array.Clear takes the array, then the starting item in the array and the number items in the array. In this example we clear the entire array, but that is not required.

using System;

namespace ArrayLearning
{
    class Program
    {
        static int[] highScores = new int[12];

        static void Main(string[] args)
        {
            // keep that top 12 high scores
            AddScore(10100);
            AddScore(13710);
            AddScore(14190);
            AddScore(12130);
            AddScore(12130);
            AddScore(16140);
            AddScore(19320);
            AddScore(07250);
            AddScore(18140);
            AddScore(08090);
            AddScore(10010);
            AddScore(14380);
            AddScore(18140);
            AddScore(12190);
            AddScore(19320);

            // Clear the high scores
            ClearHighScores();
        }

        static void AddScore(int newScore)
        {
            // Pre-sort the high scores in case somehow the
            // first one is not the lowest.
            Array.Sort(highScores);

            // If the new score is greater than the lowest
            // high score, replace the lowest high score
            if (highScores[0] < newScore)
                highScores[0] = newScore;

            // Now resort the scores as the new score may
            // not be in the right place
            Array.Sort(highScores);

            DisplayHighScores();
        }

        public static void ClearHighScores()
        {
            Console.WriteLine("Clearing High Scores!");
            Array.Clear(highScores, 0, highScores.Length);
            DisplayHighScores();
        }

        private static void DisplayHighScores()
        {
            // Print the new high scores
            for (int i = highScores.Length - 1; i > -1; i--)
            {
                Console.WriteLine(highScores[i]);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
            Console.WriteLine();
        }
    }
}

Array.IndexOf

Maybe you want to display the place in the top 12 that the player scored. However, the way we are adding the score does not track the new score’s place. So we need to find the place. Here is a small enhancement to the above code that demonstrates the use of Array.IndexOf to find the place.

Notice the addition of the DisplayCurrentPlace function and it’s use of Array.IndexOf. Also since the array is actually sorted with the lowest number at index 0 and the highest score at index 11, I can just subtract the index from the max lengh of 12 high scores to get the correct place.

using System;

namespace ArrayLearning
{

    class Program
    {
        public static int MAX = 12;
        static int[] highScores = new int[MAX];

        static void Main(string[] args)
        {
            // keep that top 12 high scores
            AddScore(10100);
            AddScore(13710);
            AddScore(14190);
            AddScore(12130);
            AddScore(12130);
            AddScore(16140);
            AddScore(19320);
            AddScore(07250);
            AddScore(18140);
            AddScore(08090);
            AddScore(10010);
            AddScore(14380);
            AddScore(18140);
            AddScore(12190);
            AddScore(19320);
            AddScore(06320);

            // Clear the high scores
            ClearHighScores();
        }

        static void AddScore(int newScore)
        {
            // Pre-sort the high scores in case somehow the
            // first one is not the lowest.
            Array.Sort(highScores);

            // If the new score is greater than the lowest
            // high score, replace the lowest high score
            if (highScores[0] < newScore)
            {
                highScores[0] = newScore;

                // Now resort the scores as the new score may
                // not be in the right place
                Array.Sort(highScores);

                DisplayHighScores();
                DisplayCurrentPlace(newScore);
            }
        }

        public static void ClearHighScores()
        {
            Console.WriteLine("Clearing High Scores!");
            Array.Clear(highScores, 0, highScores.Length);
            DisplayHighScores();
        }

        private static void DisplayHighScores()
        {
            // Print the new high scores
            for (int i = highScores.Length - 1; i > -1; i--)
            {
                Console.WriteLine(highScores[i]);
            }
        }

        private static void DisplayCurrentPlace(int newScore)
        {
            Console.WriteLine(String.Format("You placed number {0} out the top 12.", MAX - Array.IndexOf(highScores, newScore)));

            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
            Console.WriteLine();
        }
    }
}

Well, these were three simple examples of using the Array class. As you can see it is little more than a “function holder”.

If you have an example of a function in the Array class, please post it here in the comments.

Originally posted here: The Array class in C#

String and StringBuilder in C#

So we all use the Strings in C# and most of us consider ourselves experts. But are we really experts. When you’re getting tested and you don’t have Visual Studio or MSDN in front of you, are you ready to answer the questions with confidence?

Sometimes it is worth while to re-learn the basics because often simple features you are not using would save you time and prevent you from failing to appear as knowledgeable as you really are. Especially if you have not had a project where you manipulate strings, because you do other complex tasks and you do little more with strings than assign them values and compare them.

Well, here are the two links to the String and StringBuilder objects on MSDN.

Take a moment and read the MSDN pages about these objects even if you have read them before.

Here are some questions that you should answer about these classes.

  1. Which is mutable and which is immutable? What does that mean?

    Answer:

    String is immutable. That means that once you create a string, it cannot be altered in place in memory, but instead, any alteration causes a copy with the modification to be created in a new memory location and the reference is updated to refer to the copy. For example if you append a character you actually get a whole new string in a whole new memory location.

    StringBuilder is mutable. That means that you can change the object in place in memory without creating a copy. For example, if you append a character to StringBuilder it can add it to the same space in memory. There is one exception. If you add so many characters that the next character you add make the string bigger than the memory location’s capacity, a new object in memory is created. The default capacity for this implementation is 16 characters, and the default maximum capacity is Int32.MaxValue. (1) So if you are playing with Strings greater than 16 characters, you should instantiate your StringBuilder objects with a capacity greater than 16.

  2. So can you modify a string in place in memory?

    Answer:

    No. And yes.

    Read this MSDN article: How to: Modify String Contents (C# Programming Guide)

    The short version of the above article is that you can’t normally. But if you use “unsafe” you can, the above link provides the following unsafe code:

    class UnsafeString
    {
        unsafe static void Main(string[] args)
        {
            // Compiler will store (intern)
            // these strings in same location.
            string s1 = "Hello";
            string s2 = "Hello";
    
            // Change one string using unsafe code.
            fixed (char* p = s1)
            {
                p[0] = 'C';
            }
    
            //  Both strings have changed.
            Console.WriteLine(s1);
            Console.WriteLine(s2);
    
            // Keep console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
    

    Would you actually do this though?

  3. What is the easiest way to reverse a String?
        public static string ReverseString(string s)
        {
    	char[] arr = s.ToCharArray();
    	Array.Reverse(arr);
    	return new string(arr);
        }
    

    Notice another C# class called Array was used. This class, like String and StringBuilder, is another class that you may be forgetting about an overlooking.

    When I was asked how to reverse a string, the Array.Reverse function did not come to mind and so I recreated it with this function, which obviously takes more time and a developer’s time is too expensive to recreate work already done for you.

        private static String Reverse(String inString)
        {
            char[] myChars = inString.ToCharArray();
            for (int i = 0, j = inString.Length - 1; i < inString.Length / 2; i++, j--)
            {
                char tmp = inString[j];
                myChars[j] = inString[i];
                myChars[i] = tmp;
            }
            return new string(myChars);
        }
    
  4. Which is more efficient for concatenation or appending characters, String or StringBuilder?

    StringBuilder is by far more efficient. Microsoft has a knowledge base article on this here: http://support.microsoft.com/kb/306822

    I changed the code slightly to use the Stopwatch to time the ticks to get more accurate data.

    using System;
    using System.Diagnostics;
    
    namespace StringBuilderPerformance
    {
        class Program
        {
            static void Main(string[] args)
            {
                // The greater the loops the better the performance ratio
                const int sLen = 30, Loops = 10000;
                int i;
                string sSource = new String('X', sLen);
                string sDest = "";
                //
                // Time string concatenation.
                //
                Stopwatch timer = new Stopwatch();
                timer.Start();
                for (i = 0; i < Loops; i++) sDest += sSource;
                timer.Stop();
                long stringTicks = timer.ElapsedTicks;
                Console.WriteLine("Concatenation took " + stringTicks + " ticks.");
                //
                // Time StringBuilder.
                //
                timer.Reset();
                timer.Start();
                System.Text.StringBuilder sb = new System.Text.StringBuilder((int)(sLen * Loops * 1.1));
                for (i = 0; i < Loops; i++) sb.Append(sSource);
                sDest = sb.ToString();
                timer.Stop();
                long stringBuilderTicks = timer.ElapsedTicks;
                Console.WriteLine("String Builder took " + stringBuilderTicks + " ticks.");
                Console.WriteLine("Using StringBuilder takes " + ((double)stringBuilderTicks / (double)stringTicks * (double)100).ToString("F") + "% of the time that using String takes.");
    
                //
                // Make the console window stay open
                // so that you can see the results when running from the IDE.
                //
                Console.WriteLine();
                Console.Write("Press any key to finish ... ");
                Console.ReadKey();
            }
        }
    }
    

    Here are the results:

    Concatenation took 5338055 ticks.
    String Builder took 2213 ticks.
    Using StringBuilder takes 0.04% of the time that using String takes.

    Press any key to finish …

Anyway, I hope this post helps you remember the basics.