DEV Community

John Peters
John Peters

Posted on • Edited on

.NET Looks at Functional Programming Techniques.

Consder this code:

 private ModelThing SaveThing(ModelThing modelThing)
        {

            Thing modelChangesAsEntity = modelThing.ToEntity(User.Identity.Name);
            Func<ConfigEntities.Thing, ConfigEntities.Thing> UpdateExisting = (existingThing) =>
            {
                modelChangesAsEntity.ID = existingThing.ID;              
                _store.Entry(existingThing).CurrentValues.SetValues(modelChangesAsEntity);
                _store.SaveChanges();                 
                return existingThing;
            }; 
            Func<int, ConfigEntities.Thing> findExistingByID = (modelID) =>
            {
                var entityfound = _store.ThingsControls.FirstOrDefault(item => item.ID == modelID);
                return entityfound;
            };

            Func<ModelThing, ConfigEntities.Thing> findSimilar = (model) =>
            {
                var found = _store.ThingsControls.FirstOrDefault(item =>
                      item.DisplayName == modelThing.DisplayName &&
                      item.ThingGroupID == modelThing.GroupID &&
                      item.Type == modelThing.Type);
                return found;
            };
            //work flow starts here
            var foundByID = findExistingByID(modelThing.ID);
            if (foundByID != null)
            {
                UpdateExisting(foundByID);
            }
            else
            {
                var found = findSimilar(modelThing);               
                if (found != null)
                {
                      var updated =  UpdateExisting(found);
                    _store.SaveChanges();
                    modelThing.ID = updated.ID;
                }
                else
                {
                    _store.ThingsControls.Add(modelChangesAsEntity);
                    _store.SaveChanges();
                    modelThing.ID = modelChangesAsEntity.ID;
                }
            }
            return modelThing;
        }
Enter fullscreen mode Exit fullscreen mode

We see some functional programming styles above. One of them being a static helper method ToEntity(). The rest are de-marked by the Func keyword.

Yes it could be argued there's no real value here if we have the perspective these functions will always (throughout the lifetime of this application) always remain here. On the other hand we are separating concerns within a method itself. We could have refactored to other methods which work perfectly.

The takeaway here is that prior to adding these functions we had a monolith of code in SaveThing method. A flow controlled solely on If/Then statements which are still there, but the code in each branch is simply a call to another function.

What's the point? Well we are demonstrating to any code reviewer that we are thinking "SOLIDLY". This is a pre-requisite to creating reusable toolboxes for the further usuages. Functions (and methods) should only do one thing!

Unfortunately, C# doesn't treat Functions as a first class citizen like a Class. Javascript does!

BTW I submitted code similar to this 7 years ago for a code review. Nobody liked it. I had to rip it out and put in method calls which for their eyes, at the time, was easier to take.

I do admit that this example may be a bit much, but learning how to use Functions allows use to use Functions in method parameters, to "call-back" something, to get very specific information, at just the right time.

JWP2020

Top comments (18)

 
jwp profile image
John Peters • Edited

Its not demeaning just not first-class in same way as Typescript/JavaScript.

I think if it's truly first class it should be able to do this:

namespace myFunctionLibrary
{
    Func<string> junk=()=>"junk";
}

It has a name and namespace, it doesn't need a Class wrapper.
It's well defined as the only input and output parms are string.

Thread Thread
 
thebuzzsaw profile image
Kelly Brown

Many consider the fact that Java and C# cannot have executing code outside of classes a feature. On that same note, they consider JavaScript allowing anything and everything at the top level to be an anti-feature. So, you can rain on C#'s parade all you want, but the decision to mandate structure is not inherently wrong or "second-class".

Thread Thread
 
jwp profile image
John Peters

What's mandating about anonymous classes, or use of Dynamic? Typescript is more modern than C# and gives the developer a choice of strong and weak typing. Most of all it treats functions as first class citizens.

I'm not raining on any parades here, that's your idea of what I'm doing. I'm just proving my point that .NET people don't really like accepting Functional Programming ideas outside of their curtained niche. Shoot the majority don't embrace Extension methods.

Thread Thread
 
thebuzzsaw profile image
Kelly Brown

What's mandating about anonymous classes, or use of Dynamic?

I was referring to their decision to mandate namespaces and classes contain the code that actually runs (namely methods and variables).

Typescript is more modern than C# and gives the developer a choice of strong and weak typing.

Weak typing sux. Don't need it.

I'm just proving my point that .NET people don't really like accepting Functional Programming ideas outside of their curtained niche. Shoot the majority don't embrace Extension methods.

I love extension methods. I don't know many people who hate 'em.

What's your whole angle with pushing functional programming into .NET projects? If the people you work with don't care for functional programming and are solving problems just fine in OOP or other paradigms, what do you care? If you wanna use functional programming in your own projects, knock yourself out. I see plenty of functional programming done in C#, though.

Thread Thread
 
jwp profile image
John Peters

Weak Typing does suck except for disciplined OOP folks who know when to use it to their advantage.

Ya I love extension methods too, they are the only real functional style (apart from the Func) in C#. No fancy interface or class defs needed there, as they automatically telegraph the interface, and there's no way to get by it.

Functional programming using extension methods is my angle. That's all.

Thread Thread
 
saint4eva profile image
saint4eva • Edited

Lambda,
Linq,
Extension Method,
Anonymous Method,
Delegates,
Switch Expression,
Local Method,
Pattern Matching,
Higher Order Function etc.
C# has both functional and OOP capabilities.

Thread Thread
 
jwp profile image
John Peters

You're right...

 
jwp profile image
John Peters

That's why I say functions are not first class. Even though MSFT claims they are first class.
In Typescript and JavaScript, functions as well as classes sit at same layer. C# forces functions inside of a class.

Collapse
 
antoinega profile image
Antoine

Hi,

You should have a look at F#. I have learned it using FAKE, it was a great way to learn about functional programming.

Collapse
 
thebuzzsaw profile image
Kelly Brown

Modern analyzers would propose you change those local delegate variables to local methods.

Collapse
 
jwp profile image
John Peters

True...

I did this example based on the only real functional constructs we have in C# which are 1) Func and 2)Extension methods. I've worked in shops where they were adverse to Extension Methods, thus the reason the title is as it is. Unfortunately for C# Func, despite what MSFT says are not 1st class citizens as they are in Typescript/JavaScript. Maybe this is the reason I've seen resistance to extension methods.

Collapse
 
thebuzzsaw profile image
Kelly Brown

Unfortunately for C# Func, despite what MSFT says are not 1st class citizens as they are in Typescript/JavaScript.

As noted in the other discussion thread, you have yet to defend this claim. The C# syntax simply isn't what you like, but they have all the same abilities.

Collapse
 
saint4eva profile image
saint4eva

A lot of developers use Linq, I believe.

Collapse
 
jwp profile image
John Peters

Can functions be declared outside of a class in C#?

Collapse
 
thebuzzsaw profile image
Kelly Brown

static methods are mechanically equivalent to freestanding methods. This seems like an arbitrary qualification for being "first-class".

Thread Thread
 
jwp profile image
John Peters

Yes but I can't do this... in C# like I can in Typescript

namespace myClassAndFunctionLibrary
{
    public Func<string> junk=()=>"junk";
    public Class MyClass{ }
}
Thread Thread
 
thebuzzsaw profile image
Kelly Brown

Sure, but my point is you are not missing anything in terms of capability.

namespace MyLibrary
{
    public static class J
    {
        public static Func<string> unk = () => "junk";
    }
}

There. Now you can access it via J.unk. Happy? I mean, what is it you really want? You're gonna need to find far worse things to leverage any kind of meaningful criticism against C# here.

Thread Thread
 
jwp profile image
John Peters

Or here's one...


namespace MyLibrary
{
    public static class func
    {
       public static Func<string> junk = () => "junk";
       public static Func<string,string> append = (item)=> item + "appended";
       public static string append2(this string input){  return input + "appended";   }
    }
}

//elsewhere

var junk = func.Junk();
var appended  = func.append("prefix");
var appended2 = "prefix".append2();

The C# Equivalent of first class functions in Typescript/JavaScript are Extension Methods.