Table of Contents [Hide/Show]
Chapter 8 - C# 4.0 New Language Features C# 4.0 Features Listing 8-1 : COM Interop and Optional Parameters. Listing 8-2 : Optional Parameters. Listing 8-3 : Named Arguments. Listing 8-4 : Named Arguments and Optional Parameters in LINQ Queries. Listing 8-7 : Dynamic type to parse CSV file line. Listing 8-8 : Dynamic type to parse CSV files (header and process lines). Listing 8-9 : LINQ over Dynamic Types. Listing 8 : The dynamic Keyword. Listing 8-14 : COM Interop and LINQ. Listing 8 : COM Interop.
public void Listing_8_1_COMInteropWithAndWithoutOptionalParameters() { string fileName = Path.Combine( Environment.CurrentDirectory, "Data/SampleExcel.xlsx"); // Old way – before optional parameters var excel = new Microsoft.Office.Interop.Excel.Application(); try { Microsoft.Office.Interop.Excel.Workbook workBook = excel.Workbooks.Open(fileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); // do work with Excel... workBook.Close(false, fileName); } finally { excel.Quit(); } // New Way – Using optional parameters var excelNew = new Microsoft.Office.Interop.Excel.Application(); try { Microsoft.Office.Interop.Excel.Workbook workBook = excelNew.Workbooks.Open(fileName); // do work with Excel... workBook.Close(false, fileName); } finally { excelNew.Quit(); } }
public void Listing_8_2_OptionalParameters() { OldWay oldWay = new OldWay(); oldWay.DoSomething( "({0},{1}) Old way – defaults from overloaded methods."); NewWay newWay = new NewWay(); // the following statement are logically identical // (except for the string value passed in) newWay.DoSomething( "({0},{1}) New way – defaults in param definitions."); newWay.DoSomething( "({0},{1}) New way – formatString and param1 passed in only.", 0); newWay.DoSomething( "({0},{1}) New way – formatString, param1 and param2 passed in.", 0, true); } public class OldWay { // multiple overloads call the one master // implementation of a method that handles all inputs public void DoSomething(string formatString) { // passing 0 as param1 default, // and true as param2 default. DoSomething(formatString, 0, true); } public void DoSomething(string formatString, int param1) { DoSomething(formatString, param1, true); } public void DoSomething(string formatString, bool param2) { DoSomething(formatString, 0, param2); } // the actual implementation. All variations call this // method to implement the methods function. public void DoSomething( string formatString, int param1, bool param2) { Console.WriteLine( String.Format(formatString, param1, param2)); } } public class NewWay { // optional parameters have a default specified. // optional parameters must come after normal params. public void DoSomething( string formatString, int param1 = 0, bool param2 = true) { Console.WriteLine( String.Format(formatString, param1, param2)); } public void M1(string s, int i = 1) { } //public void M2(System.Drawing.Point p = new System.Drawing.Point()) { } public void M3(System.Drawing.Point p = default(System.Drawing.Point)) { } public void M4(int i = 1, params string[] values) { } /* ERRORS – //"Optional parameters must appear after all required parameters" public void M1 (int i = 1, string s) {} //"Default parameter value for 'p' must be a compile–time constant" //Can't use a constructor that has parameters. public void M2(Point p = new Point(0,0)) {} //"Default parameter value for 'p' must be a compile–time constant" //(Must be a value type (struct or built–in value types only)) public void M5(StringBuilder p = new StringBuilder()) {} //"A ref or out parameter cannot have a default value" public void M6(int i = 1, out string s = "") {} //"Cannot specify a default value for a parameter array" public void M7(int i = 1, params string[] values = "test") {} */ }
(0,True) Old way – defaults from overloaded methods. (0,True) New way – defaults in param definitions. (0,True) New way – formatString and param1 passed in only. (0,True) New way – formatString, param1 and param2 passed in.
public void Listing_8_3_NamedArguments() { // reversing the order of arguments. Point p1 = new Point(y: 100, x: 10); // using an expression as the argument value. int width = 600; Point p2 = new Point(y: width – 100, x: 10); /* ERRORS //"Named argument 'x' specifies a parameter for which a // positional argument has already been given" Point p3 = new Point(10, x: 10); // "Named argument specifications must appear after all // fixed arguments have been specified" Point p4 = new Point(y: 100, 10); // "The best overload for '.ctor' does not have a // parameter named 'x'" Point p5 = new Point(x: 10); * */ // skipping and reordering arguments NewWay newWay = new NewWay(); // skipping an optional parameter newWay.DoSomething( "({0},{1}) New way – param1 skipped.", param2: false); // any order, but if it doesn't have a default // it must be specified by name somewhere! newWay.DoSomething( param2: false, formatString: "({0},{1}) New way – params specified" + " by name, in any order.", param1: 5); } public class NewWay { // optional parameters have a default specified. // optional parameters must come after normal params. public void DoSomething( string formatString, int param1 = 0, bool param2 = true) { Console.WriteLine( String.Format(formatString, param1, param2)); } public void M1(string s, int i = 1) { } //public void M2(System.Drawing.Point p = new System.Drawing.Point()) { } public void M3(System.Drawing.Point p = default(System.Drawing.Point)) { } public void M4(int i = 1, params string[] values) { } /* ERRORS – //"Optional parameters must appear after all required parameters" public void M1 (int i = 1, string s) {} //"Default parameter value for 'p' must be a compile–time constant" //Can't use a constructor that has parameters. public void M2(Point p = new Point(0,0)) {} //"Default parameter value for 'p' must be a compile–time constant" //(Must be a value type (struct or built–in value types only)) public void M5(StringBuilder p = new StringBuilder()) {} //"A ref or out parameter cannot have a default value" public void M6(int i = 1, out string s = "") {} //"Cannot specify a default value for a parameter array" public void M7(int i = 1, params string[] values = "test") {} */ }
(0,False) New way – param1 skipped. (5,False) New way – params specified by name, in any order.
public void Listing_8_4_NamedAndOptionalLINQParameters() { var q = from c in Contact.SampleData() where c.State == "CA" select new Contact( c.FirstName, c.LastName, state: c.State, dateOfBirth: c.DateOfBirth ); foreach (var c in q) Console.WriteLine("{0}, {1} ({2}) – {3}", c.LastName, c.FirstName, c.DateOfBirth.ToShortDateString(), c.State); } public class Contact { // Constructor defined with optional arguments public Contact( string firstName, string lastName, DateTime dateOfBirth, string email = "", // optional string phone = "", // optional string state = "Other") // optional { FirstName = firstName; LastName = lastName; DateOfBirth = dateOfBirth; Email = email; Phone = phone; State = state; } public string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } public string Phone { get; set; } public DateTime DateOfBirth { get; set; } public string State { get; set; } public static List<Contact> SampleData() { return new List<Contact> { new Contact ("Barney", "Gottshall", new DateTime(1945,10,19), phone: "885 983 8858", email: "bgottshall@aspiring–technology.com", state: "CA"), new Contact ("Armando", "Valdes", new DateTime(1973,12,09), phone: "848 553 8487", email: "val1@aspiring–technology.com", state: "WA" ), new Contact ("Adam", "Gauwain", new DateTime(1959,10,03), phone: "115 999 1154", email: "adamg@aspiring–technology.com", state: "AK" ), new Contact ("Jeffery", "Deane", new DateTime(1950,12,16), phone: "677 602 6774", email: "jeff.deane@aspiring–technology.com", state: "CA" ), new Contact ("Collin", "Zeeman", new DateTime(1935,02,10), phone: "603 303 6030", email: "czeeman@aspiring–technology.com", state: "FL" ), new Contact ("Stewart", "Kagel", new DateTime(1950,02,20), phone: "546 607 5462", email: "kagels@aspiring–technology.com", state: "WA" ), new Contact ("Chance", "Lard", new DateTime(1951,10,21), phone: "278 918 2789", email: "lard@aspiring–technology.com", state: "WA" ), new Contact ("Blaine", "Reifsteck", new DateTime(1946,05,18), phone: "715 920 7157", email: "blaine@aspiring–technology.com", state: "TX" ), new Contact ("Mack", "Kamph", new DateTime(1977,09,17), phone: "364 202 3644", email: "mack.kamph@aspiring–technology.com", state: "TX" ), new Contact ("Ariel", "Hazelgrove", new DateTime(1922,05,23), phone: "165 737 1656", email: "arielh@aspiring–technology.com", state: "OR" ) }; } }
Gottshall, Barney (10/19/1945) – CA Deane, Jeffery (12/16/1950) – CA
public void Listing_8_7_CSVLine() { // To show the code for CSVLine. } public class CsvLine : System.Dynamic.DynamicObject { string[] _lineContent; List<string> _headers; public CsvLine(string line, List<string> headers) { this._lineContent = line.Split(','); this._headers = headers; } public override bool TryGetMember( GetMemberBinder binder, out object result ) { result = null; // find the index position and get the value int index = _headers.IndexOf(binder.Name); if (index >= 0 && index < _lineContent.Length) { result = _lineContent[index]; return true; } return false; } public override bool TryGetIndex( GetIndexBinder binder, object[] indexes, out object result) { result = null; int index = (int)indexes[0]; if (index >= 0 && index < _lineContent.Length) { result = _lineContent[index]; return true; } return false; } }
public void Listing_8_8_CsvParser() { // To show the code for CsvParser. } public class CsvParser : IEnumerable { List<string> _headers; string[] _lines; public CsvParser(string csvContent) { _lines = csvContent.Split('\n'); // grab the header row and remember positions if (_lines.Length > 0) _headers = _lines[0].Split(',').ToList(); } public IEnumerator GetEnumerator() { // skip the header line bool header = true; foreach (var line in _lines) if (header) header = false; else yield return new CsvLine(line, _headers); } }
public void Listing_8_9_DynamicLookupOnCSVFile() { string content = "FirstName,LastName,State\nTroy,Magennis,TX\nJanet,Doherty,WA"; var q = from dynamic c in new CsvParser(content) where c.State == "WA" select c; foreach (var c in q) { Console.WriteLine("{0}, {1} ({2})", c.LastName, c.FirstName, c.State); } } public class CsvLine : System.Dynamic.DynamicObject { string[] _lineContent; List<string> _headers; public CsvLine(string line, List<string> headers) { this._lineContent = line.Split(','); this._headers = headers; } public override bool TryGetMember( GetMemberBinder binder, out object result ) { result = null; // find the index position and get the value int index = _headers.IndexOf(binder.Name); if (index >= 0 && index < _lineContent.Length) { result = _lineContent[index]; return true; } return false; } public override bool TryGetIndex( GetIndexBinder binder, object[] indexes, out object result) { result = null; int index = (int)indexes[0]; if (index >= 0 && index < _lineContent.Length) { result = _lineContent[index]; return true; } return false; } } public class CsvParser : IEnumerable { List<string> _headers; string[] _lines; public CsvParser(string csvContent) { _lines = csvContent.Split('\n'); // grab the header row and remember positions if (_lines.Length > 0) _headers = _lines[0].Split(',').ToList(); } public IEnumerator GetEnumerator() { // skip the header line bool header = true; foreach (var line in _lines) if (header) header = false; else yield return new CsvLine(line, _headers); } }
Doherty, Janet (WA)
public void Listing_8_DynamicKeyword() { dynamic o = 1; o.ThisMethodIsNotDefinedAnywhere(); object os = "test"; // ERROR – 'object' does not contain // a definition for 'ToUpper' //os.ToUpper(); // we must cast to access the methods // on the underlying string type. ((string)os).ToUpper(); // var works, but only method scoped, // and can't be used in a Generic type. var vs = "test"; vs.ToUpper(); // ERROR – 'var' may only appear within // a local variable declaration //List<var> list = new List<var>(); // dynamic work in all cases dynamic ds = "test"; ds.ToUpper(); List<dynamic> dlist = new List<dynamic>(); }
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'int' does not contain a definition for 'ThisMethodIsNotDefinedAnywhere' at CallSite.Target(Closure , CallSite , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0) at SampleQueries.Chapter08Samples.Listing_8_DynamicKeyword() in C:\Users\Troy\Desktop\HOL Book\LINQ to Objects using CSharp 4 Samples\LINQ to Objects using CSharp 4 Sample Queries\Chapter08Samples.cs:line 409
public void Listing_8_14_COMInteropLINQ() { string filename = Path.Combine( Environment.CurrentDirectory, "Data/SampleExcel.xlsx"); const int firstNameCol = 0; const int lastNameCol = 1; const int stateCol = 5; var q = from row in GetExcelRowEnumerator(filename, 1) where row[stateCol] == "WA" select row; Console.WriteLine("Customers in WA ({0})", q.Count()); foreach (var row in q) { Console.WriteLine("{0}, {1}", row[lastNameCol].ToUpper(), row[firstNameCol] ); } }
Customers in WA (3) VALDES, Armando KAGEL, Stewart LARD, Chance
public void Listing_8_COMInterop() { // From the Microsoft Samples var excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = true; excel.Workbooks.Add(); // optional arguments excel.Cells[1, 1].Value = "Process Name"; // dynamic property set excel.Cells[1, 2].Value = "Memory Usage"; // dynamic property set var processes = Process.GetProcesses() .OrderByDescending(p => p.WorkingSet64) .Take(10); int i = 2; foreach (var p in processes) { excel.Cells[i, 1].Value = p.ProcessName; // dynamic property set excel.Cells[i, 2].Value = p.WorkingSet64; // dynamic property set i++; } Microsoft.Office.Interop.Excel.Range range = excel.Cells[1, 1]; // dynamic conversion Excel.Chart chart = excel.ActiveWorkbook.Charts. Add(After: excel.ActiveSheet); // named and optional arguments chart.ChartWizard( Source: range.CurrentRegion, Title: "Memory Usage in " + Environment.MachineName); //named+optional chart.ChartStyle = 45; chart.CopyPicture(Excel.XlPictureAppearance.xlScreen, Excel.XlCopyPictureFormat.xlBitmap, Excel.XlPictureAppearance.xlScreen); }