Skip to content

Latest commit

 

History

History
158 lines (130 loc) · 4.49 KB

Linq-CSharp.md

File metadata and controls

158 lines (130 loc) · 4.49 KB

Using LINQ on the client-side

WebSharper provides support to process IEnumerable sequences using LINQ queries on the client side.

Simple queries

You can use LINQ query syntax in client-side code like you would in .NET.

using System;
using System.Linq;
using System.Collections.Generic;
using WebSharper;

namespace TestLinq
{
    [JavaScript]
    public class App
    {
        public static void Main()
        {
            var people = new[] { "Don", "Simon", "Rich", "Joe", "Martin" };

            var oddPeople =
                from person in people
                where person.Length % 2 == 1
                orderby person.Length
                select person;

            Console.Log("People whose names have an odd length:");
            foreach (var person in oddPeople)
            {
                Console.Log("  " + person);
            }
            // prints:
            // People whose names have an odd length:
            //   Don
            //   Simon
            //   Joe
        }
    }
}

Of course, you can use explicit LINQ extension methods if you prefer.

        public static void Main()
        {
            var people = new[] { "Don", "Simon", "Rich", "Joe", "Martin" };

            var oddPeople = people
                .Where(person => person.Length % 2 == 1)
                .OrderBy(person => person.Length);

            Console.Log("People whose names have an odd length:");
            foreach (var person in oddPeople)
            {
                Console.Log("  " + person);
            }
            // prints:
            // People whose names have an odd length:
            //   Don
            //   Simon
            //   Joe
        }

Other Linq methods

WebSharper provides proxies for all IEnumerable extension methods from System.Linq, such as .Concat(), .ToArray() or .ElementAt():

        public static void Main()
        {
            var people = new[] { "Don", "Simon", "Rich", "Joe", "Martin" };
            var morePeople = people.Concat(new[] { "Xavier", "Evan" }).ToArray();

            Console.Log("The sixth person is", morePeople.ElementAt(5));
            // prints:
            // The sixth person is Xavier
        }

Using custom comparers

Advanced uses of Linq methods are possible, such as custom comparers. Here is an example where we make a sequence's items distinct by their length using an EqualityComparer:

        public static void Main()
        {
            var people = new[] { "Don", "Simon", "Rich", "Joe", "Martin" };

            var distinctPeople = people.Distinct(new ByLength());

            foreach (var person in distinctPeople)
            {
                Console.Log(person);
            }
            // prints:
            //   Don
            //   Simon
            //   Rich
            //   Martin
        }

        public class ByLength : EqualityComparer<string>
        {
            override public bool Equals(string x, string y)
            {
                return x.Length == y.Length;
            }

            public override int GetHashCode(string x)
            {
                return x.Length;
            }
        }

Methods dealing with default values

Some Linq methods use the default value of the element type. For example, .FirstOrDefault() returns the first element of the IEnumerable, or a default type if it is empty. This default value depends on the type: for example, if the element type is int, then the default value is 0, whereas if the element type is a class, then the default value is null. WebSharper can provide the correct default value, on the condition that the element type is known statically. For example, the following will run correctly:

        public static void Main()
        {
            var people = new string[] { };
            var onePerson = people.FirstOrDefault();
            Console.Log(onePerson);
            // prints:
            // null
        }

However, the following will fail to compile because the element type is not known statically:

        public static T GetDefaultPerson<T>(IEnumerable<T> people)
        {
            return people.FirstOrDefault();
            // compile error:
            // Macro 'WebSharper.MacroModule+DefaultOf' requires a resolved type argument.
        }

In this case, you can add the [Inline] attribute to the method to make its content to be inserted at every call point, with all code generation needing known types to be resolved appropriately.