Hooked on LINQ

Hooked on LINQ - Developers' Wiki
for .NET Language Integrated Query

Companion book for this site
LINQ to Objects Using C# 4.0:
Using and Extending LINQ to Objects and Parallel LINQ (PLINQ)
Quick Search

Advanced Search »
Edit

Chapter 8 - C# 4.0 New Language Features





Edit

C# 4.0 Features

Edit

Listing 8-1 : COM Interop and Optional Parameters.

This sample shows how optional parameters make calling Excel using COM-Interop easier.

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();
    }
}
 



Top



Edit

Listing 8-2 : Optional Parameters.

This sample shows how to call methods using optional parameters.

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") {}
 
    */
 
}
 

Console output (Execution time: 0ms): [Hide/Show]


Top



Edit

Listing 8-3 : Named Arguments.

This sample shows how to call methods using named arguments.

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") {}
 
    */
 
}
 

Console output (Execution time: 0ms): [Hide/Show]


Top



Edit

Listing 8-4 : Named Arguments and Optional Parameters in LINQ Queries.

This sample shows how to use named arguments and optional parameters in a LINQ query.

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" )
        };
 
    }
}
 

Console output (Execution time: 29ms): [Hide/Show]


Top



Edit

Listing 8-7 : Dynamic type to parse CSV file line.

Class to represent a dynamic type that will allow the LINQ code (or any other code) to parse a single comma-separated line and access data at runtime based on thenames in the header row of the text file.

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;
    }
}
 



Top



Edit

Listing 8-8 : Dynamic type to parse CSV files (header and process lines).

The IEnumerable class that reads the header line and returns each line in the content as an instance of our CsvLine dynamic type

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);
    }
}
 



Top



Edit

Listing 8-9 : LINQ over Dynamic Types.

This sample shows how to use dynamic lookups to parse and code against CSV file data.

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);
    }
}
 

Console output (Execution time: 156ms): [Hide/Show]


Top



Edit

Listing 8 : The dynamic Keyword.

This sample shows how to use dynamic keyword in C#.

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>();
}
 

Console output (Execution time: 36ms): [Hide/Show]


Top



Edit

Listing 8-14 : COM Interop and LINQ.

This sample shows how to use COM interop and LINQ.

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] );
    }
}
 

Console output (Execution time: 1812ms): [Hide/Show]


Top



Edit

Listing 8 : COM Interop.

This Microsoft sample shows how to use COM interop.

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);
}
 



Top



If you would like to comment on this page, click on the Discuss button located on the top-right of each page. Feel free to edit any mistakes or omissions you find. If you have an objection or find in-appropriate content then contact the administrator. This website is not affiliated with Microsoft®, all content and opinions are those of the specific author and some advice, solutions and article may contain unintentional errors - please use care. Powered by ScrewTurn Wiki version 2.0.33. Some of the icons created by FamFamFam.