Section122.1:FuncandAction
Funcprovidesaholderforparameterisedanonymousfunctions.Theleadingtypesaretheinputsandthelasttype is always the return value.
//squareanumber.
Func<double,double>square=(x)=>{returnx*x;};
//getthesquareroot.
//notehowthesignaturematchesthebuiltinmethod.
Func<double,double>squareroot=Math.Sqrt;
//provideyourworkings.
Func<double,double,string>workings=(x,y)=>string.Format(“Thesqua
reof{0}is{1}.”,x,square(y))
Actionobjectsarelikevoidmethodssotheyonlyhaveaninputtype.Noresultisplacedontheevaluationstack.
//right-angledtriangle.
classTriangle
{
public doublea;
public doubleb;
publicdoubleh;
}
//Pythagoreantheorem.
Action<Triangle>pythagoras=(x)=>
x.h=squareroot(square(x.a)+square(x.b));
Triangle t=newTriangle{a=3,b=4}; pythagoras(t);
Console.WriteLine(t.h);//5.
Section122.2:Higher-OrderFunctions
A higher-order function is one that takes another function as an argument or returns a function (or both). This is commonly done with lambdas, for example when passing a predicate to a LINQ Where clause:
varresults=data.Where(p=>p.Items==0);
TheWhere()clausecouldreceivemanydifferentpredicateswhichgivesitconsiderableflexibility.
Passing a method into another method is also seen when implementing the Strategy design pattern. For example, various sorting methods could be chosen from and passed into a Sort method on an object depending on the requirements at run-time.
Section122.3:AvoidNull References
C# developers get a lot of null reference exceptions to deal with. F# developers don’t because they have the Option type. An Option<> type (some prefer Maybe<> as a name) provides a Some and a None return type. It makes it explicit that a method may be about to return a null record.
Forinstance,youcan’treadthefollowingandknowifyouwillhavetodealwithanullvalue.
varuser=_repository.GetUser(id);
Ifyoudoknowaboutthepossiblenullyoucanintroducesomeboilerplatecodetodealwithit.
varusername=user!=null?user.Name:string.Empty;
Whatifwe haveanOption<> returnedinstead?
Option<User>maybeUser=_repository.GetUser(id);
ThecodenowmakesitexplicitthatwemayhaveaNonerecordreturnedandtheboilerplatecodetocheckfor Some or None is required:
varusername=maybeUser.HasValue?maybeUser.Value.Name:string.Empty;
ThefollowingmethodshowshowtoreturnanOption<>
publicOption<User>GetUser(intid)
{
varusers=newList<User>
{
newUser{Id=1,Name=”JoeBloggs”},
newUser{Id=2,Name=”JohnSmith”}
};
varuser=users.FirstOrDefault(user=>user.Id==id);
returnuser!=null?newOption<User>(user):newOption<User>();
}
HereisaminimalimplementationofOption<>.
publicstructOption<T>
{
privatereadonlyT_value;
publicTValue
{
get
{
if(!HasValue)
thrownewInvalidOperationException();
return_value;
}
}
publicboolHasValue
{
get{return_value!=null;}
}
publicOption(Tvalue)
{
_value=value;
}
publicstaticimplicitoperatorOption<T>(Tvalue)
{
returnnewOption<T>(value);
}
}
TodemonstratetheaboveavoidNull.csxcanberunwiththeC# REPL.
Asstated,thisisaminimalimplementation.Asearchfor”Maybe”NuGetpackageswillturnupanumberofgood libraries.
Immutabilityiscommoninfunctionalprogrammingandrareinobjectorientedprogramming. Create,forexample,anaddresstypewithmutablestate:
publicclassAddress()
{
public stringLine1{get;set;}
public stringLine2{get;set;}
publicstringCity{get;set;}
}
Any piece of code could alter any property in the above object.Now create the immutable address type:
publicclassAddress()
{
public readonly stringLine1;
public readonly stringLine2;
publicreadonlystringCity;
publicAddress(stringline1,stringline2,stringcity)
{
Line1=line1;
Line2=line2;
City=city;
}
}
Bear in mind that having read-only collections does not respect immutability. For example,
publicclassClassroom
{
publicreadonlyList<Student>Students;
publicClassroom(List<Student>students)
{
Students=students;
}
}
is not immutable, as the user of the object can alter the collection (add or remove elements from it). In order to make it immutable, one has either to use an interface like IEnumerable, which does not expose methods to add, or to make it a ReadOnlyCollection.
publicclassClassroom
{
publicreadonlyReadOnlyCollection<Student>Students;
publicClassroom(ReadOnlyCollection<Student>students)
{
Students=students;
}
}
List<Students>list=newList<Student>();
//addstudents
Classroomc=newClassroom(list.AsReadOnly());
Withtheimmutableobjectwehavethefollowingbenefits:
- Itwillbeinaknownstate(othercodecan’tchangeit).
- It is thread safe.
- The constructor offers a single place for validation.
- Knowing that the object cannot be altered makes the code easier to understand.
Section122.5:Immutablecollections
TheSystem.Collections.ImmutableNuGetpackageprovidesimmutablecollectionclasses.
varstack=ImmutableStack.Create<int>();
varstack2=stack.Push(1);//stackisstillempty,stack2contains1
varstack3=stack.Push(2);//stack2stillcontainsonlyone,stack3has2,1
Creatingandaddingitems
Creatingusingthebuilder
CertainimmutablecollectionshaveaBuilderinnerclassthatcanbeusedtocheaplybuildlargeimmutable instances:
varbuilder=ImmutableList.CreateBuilder<int>();//returnsImmutableList.Builder
builder.Add(1);
builder.Add(2);
varlist=builder.ToImmutable();
CreatingfromanexistingIEnumerable
varnumbers=Enumerable.Range(1,5);
varlist=ImmutableList.CreateRange<int>(numbers);
Listofallimmutablecollectiontypes:
- System.Collections.Immutable.ImmutableArray<T>System.Collections.Immutable.ImmutableDictionar
- y<TKey,TValue>System.Collections.Immutable.ImmutableHashSet<T>System.Collections.Immutable.I
- mmutableList<T>System.Collections.Immutable.ImmutableQueue<T>System.Collections.Immutable.I
- mmutableSortedDictionary<TKey,TValue>System.Collections.Immutable.ImmutableSortedSet<T>Syste
- m.Collections.Immutable.ImmutabeStack<T>
About us and this blog
We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.
Request a free quote
We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.