WebSharper provides support to process IEnumerable
sequences using LINQ
queries on the client side.
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
}
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
}
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;
}
}
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.