Joe Hummel, PhD Dept of Mathematics and Computer Science Lake Forest College Lecture 2: Working with Visual Studio and C#
Working with VS and C# 2.1 Intro to Visual Studio Working with VS
Working with VS and C# Visual Studio Microsoft’s IDE A single IDE for all.NET development –For every.NET language –For every application type –Powerful, professional tool –
Working with VS and C# Editions of Visual Studio Express : free IDE, one for each language / platform Standard : base line IDE (one for all languages and platforms) Professional : adds SQL Server Express, Object Test Bench –this is the edition you get with MSDNAA Team Editions Software engineering editions: Architect, Developer, Tester Include class designer, integrated testing & coverage tools, etc. Team Suite All 3 software engineering editions in one package Trial version available from MSDNAA Team Foundation Server The server-side component for the team editions / suite Source code control, process management, task/bug lists, reporting, etc. Built-in support for two processes: Agile and Waterfall
Working with VS and C# Working with VS 2005 Let’s work through an example… Console-based application to process US Census data –Students build an application to mine real Census data –A Nifty assignment from SIGCSE 2005
Working with VS and C# (1) Create a New Project…
Working with VS and C# (2) Select Project Type… Here you pick language & type of application to build…
Working with VS and C# (3) Code… Write code in the Code window (duh :-) –Use Solution Explorer for navigating between program files –A window isn’t visible? Make visible via View menu… Code window Solution Explorer
Working with VS and C# (4) Run… I’m a huge fan of incremental development Press F5 at any time to build and run –Beware of “console flash”, manually keep console window open… namespace CensusDataApplication { class Program { static void Main(string[] args) { // keep console window open System.Console.Read(); } namespace CensusDataApplication { class Program { static void Main(string[] args) { // keep console window open System.Console.Read(); }
Working with VS and C# (5) Visual Studio Modes VS operates in one of three modes: –Design, Running, or Debugging –If students can’t edit their code, they are probably still running!
Working with VS and C# (6) The Census Data Application Here’s the program design: census.txt 1 *
Working with VS and C# Visual Studio File Layout As a professional tool, VS produces lots of files: –solution (.sln) represents your program solution double-click on.SLN file to open an existing program in VS –project (.csproj) tracks source files, settings you have one project file for each compiled unit (.EXE,.DLL) –bin\Debug sub-directory contains.EXE & data files for example, this is where you put “census.txt”
Working with VS and C# Main Method To start, we input the data and output top 10 names: static void Main(string[] args) { string username, s, filename; ArrayList namesCollection; FamilyName nameObj; System.Console.WriteLine("** Welcome to US Census Bureau Data Mining Program **"); // assume input file is in same directory as.EXE: filename = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "census.txt"); namesCollection = ReadCensusData(filename); System.Console.WriteLine(">>1990 Census data contains a total of " + namesCollection.Count + " family names<<"); // // output top 10 family names in the census data: // System.Console.WriteLine(">>Top 10 Family Names in the 1990 US Census<<"); for (int i = 0; i < 10; i++) { nameObj = (FamilyName) namesCollection[i]; s = string.Format("{0}. {1}", i+1, nameObj.Name); System.Console.WriteLine(s); } static void Main(string[] args) { string username, s, filename; ArrayList namesCollection; FamilyName nameObj; System.Console.WriteLine("** Welcome to US Census Bureau Data Mining Program **"); // assume input file is in same directory as.EXE: filename = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "census.txt"); namesCollection = ReadCensusData(filename); System.Console.WriteLine(">>1990 Census data contains a total of " + namesCollection.Count + " family names<<"); // // output top 10 family names in the census data: // System.Console.WriteLine(">>Top 10 Family Names in the 1990 US Census<<"); for (int i = 0; i < 10; i++) { nameObj = (FamilyName) namesCollection[i]; s = string.Format("{0}. {1}", i+1, nameObj.Name); System.Console.WriteLine(s); }
Working with VS and C# Main Method (cont'd) Then we allow the user to search for a name: // // now let user search for names they are interested in... // System.Console.Write("Please enter a name you are interested in: "); username = System.Console.ReadLine(); while (!username.Equals("")) { username = username.ToUpper(); // Census data is in UPPER case // search through collection... int index; for (index = 0; index < namesCollection.Count; index++) { nameObj = (FamilyName) namesCollection[index]; if (nameObj.Name.Equals(username)) break; }//for // did we find matching family name? if (index == namesCollection.Count) // not found System.Console.WriteLine("Sorry, that name does not appear in the census data."); else System.Console.WriteLine(namesCollection[index].ToString()); System.Console.Write("Please enter a name you are interested in: "); username = System.Console.ReadLine(); }//while // // now let user search for names they are interested in... // System.Console.Write("Please enter a name you are interested in: "); username = System.Console.ReadLine(); while (!username.Equals("")) { username = username.ToUpper(); // Census data is in UPPER case // search through collection... int index; for (index = 0; index < namesCollection.Count; index++) { nameObj = (FamilyName) namesCollection[index]; if (nameObj.Name.Equals(username)) break; }//for // did we find matching family name? if (index == namesCollection.Count) // not found System.Console.WriteLine("Sorry, that name does not appear in the census data."); else System.Console.WriteLine(namesCollection[index].ToString()); System.Console.Write("Please enter a name you are interested in: "); username = System.Console.ReadLine(); }//while
Working with VS and C# FamilyName Class Here's a very simple design for the FamilyName class: public class FamilyName { public string Name; public double RawPercentFreq; public int Rank; public FamilyName(string name, double percentFrequency, int rank) { this.Name = name; this.RawPercentageFreq = percentFrequency; this.Rank = rank; } public override string ToString() { string s; s = string.Format("{0}. {1}: {2} ({3}%)", this.Rank, this.Name, this.GetFormattedPercentageFrequency(), this.RawPercentageFreq); return s; } public string GetFormattedPercentageFrequency() {... } }//class public class FamilyName { public string Name; public double RawPercentFreq; public int Rank; public FamilyName(string name, double percentFrequency, int rank) { this.Name = name; this.RawPercentageFreq = percentFrequency; this.Rank = rank; } public override string ToString() { string s; s = string.Format("{0}. {1}: {2} ({3}%)", this.Rank, this.Name, this.GetFormattedPercentageFrequency(), this.RawPercentageFreq); return s; } public string GetFormattedPercentageFrequency() {... } }//class
Working with VS and C# 2.2 Working with C# Imports aliases Foreach Using objects Generics
Working with VS and C# Import Aliases Namespaces are often imported to reduce typing This is a great convenience, but hinders readability Import aliases are a good compromise: using SC = System.Collections; using SIO = System.IO; static void Main(string[] args) { string username, s, filename; SC.ArrayList namesCollection;. filename = SIO.Path.Combine(... ); using SC = System.Collections; using SIO = System.IO; static void Main(string[] args) { string username, s, filename; SC.ArrayList namesCollection;. filename = SIO.Path.Combine(... );
Working with VS and C# Foreach Use foreach to iterate through collections –more convenient than standard index-based for loops // // now let user search for names they are interested in... // System.Console.Write("Please enter a name you are interested in: "); username = System.Console.ReadLine(); while (!username.Equals("")) { username = username.ToUpper(); // Census data is in UPPER case // search through collection... nameObj = null; // store object ref here if we find it, null if not foreach (FamilyName fn in namesCollection) { if (fn.Name.Equals(username)) { nameObj = fn; break; } }//foreach // // now let user search for names they are interested in... // System.Console.Write("Please enter a name you are interested in: "); username = System.Console.ReadLine(); while (!username.Equals("")) { username = username.ToUpper(); // Census data is in UPPER case // search through collection... nameObj = null; // store object ref here if we find it, null if not foreach (FamilyName fn in namesCollection) { if (fn.Name.Equals(username)) { nameObj = fn; break; } }//foreach
Working with VS and C# Generics.NET now supports generics (much like C++ templates) –generics offer you efficient, type-safe collections –see the System.Collections.Generic namespace Example: –instead of an ArrayList of FamilyNames, let's use a generic List<> static void Main(string[] args) {. List namesCollection; namesCollection = ReadCensusData(filename); nameObj = namesCollection[0]; // type-cast *not* needed static void Main(string[] args) {. List namesCollection; namesCollection = ReadCensusData(filename); nameObj = namesCollection[0]; // type-cast *not* needed private static List ReadCensusData(string filename) { List names = new List ();. return names; } private static List ReadCensusData(string filename) { List names = new List ();. return names; }
Working with VS and C# Using Objects Some objects must be closed / disposed for correct execution –files must be closed for changes to be written –database connections much be closed so others can use –heavy-weight objects must be disposed to free resources in timely way.NET offers using block to ensure close / dispose: private static SC.ArrayList ReadCensusData(string filename) {. try // to open file and read census data: { using (SIO.StreamReader reader = new SIO.StreamReader(filename)) {. }//stream is closed here no matter what happens inside using block } catch { // could not open file, output error message } private static SC.ArrayList ReadCensusData(string filename) {. try // to open file and read census data: { using (SIO.StreamReader reader = new SIO.StreamReader(filename)) {. }//stream is closed here no matter what happens inside using block } catch { // could not open file, output error message }
Working with VS and C# 2.3 Class Design in C# Properties Overriding Equals and GetHashCode XML comments
Working with VS and C# Properties Most agree that public fields are a bad design Properties allow field-like access with get/set semantics: –delete get for write-only semantics –delete set for read-only semantics public class FamilyName { private string m_Name; // private field public string Name // public property { get { return this.m_Name; } set { this.m_Name = value; } }. }//class public class FamilyName { private string m_Name; // private field public string Name // public property { get { return this.m_Name; } set { this.m_Name = value; } }. }//class System.Console.WriteLine( nameObj.Name );. nameObj.Name = "new family name"; System.Console.WriteLine( nameObj.Name );. nameObj.Name = "new family name";
Working with VS and C# Overriding Equals and GetHashCode Classes typically override Equals to work with.NET framework –overriding Equals requires overriding of GetHashCode public class FamilyName {. // Two FamilyNames are equal if names are equal: public override bool Equals(object obj) { if (obj != null && obj.GetType().Equals(this.GetType())) return this.Name.Equals(((FamilyName)obj).Name); else return false; } public override int GetHashCode() { // RULE: if 2 objects are Equals, must return same hash code: return this.Name.GetHashCode(); } public class FamilyName {. // Two FamilyNames are equal if names are equal: public override bool Equals(object obj) { if (obj != null && obj.GetType().Equals(this.GetType())) return this.Name.Equals(((FamilyName)obj).Name); else return false; } public override int GetHashCode() { // RULE: if 2 objects are Equals, must return same hash code: return this.Name.GetHashCode(); } // let collection do linear search for us: index = namesCollection.IndexOf(new FamilyName(username, 0.0, 0)); // let collection do linear search for us: index = namesCollection.IndexOf(new FamilyName(username, 0.0, 0));
Working with VS and C# XML Comments.NET supports XML comments (much like JavaDoc comments) –must enable via project Property –VS then produces.XML comment file in bin\Debug sub-directory –use NDoc tool to turn XML into HTML, MSDN, etc. /// /// This class represents... /// public class FamilyName { private string m_Name; /// /// Compares THIS object to the given obj. /// /// the object to compare to /// true if objects are same type and have same name, /// false if not /// public override bool Equals(object obj) {... } /// /// This class represents... /// public class FamilyName { private string m_Name; /// /// Compares THIS object to the given obj. /// /// the object to compare to /// true if objects are same type and have same name, /// false if not /// public override bool Equals(object obj) {... }
Working with VS and C# 2.4 What's Next? Lab exercise #2…
Working with VS and C#