DEV Community

amay077
amay077

Posted on

Kotlin's scope functions in C#

Kotlin's scope functions(.let, .also, .apply, etc) are super useful.

I want to these methods in C#.
So I just define it!

static class ObjectExtensions 
{
    // Kotlin: fun <T, R> T.let(block: (T) -> R): R
    public static R Let<T, R>(this T self, Func<T, R> block) 
    {
        return block(self);
    }

    // Kotlin: fun <T> T.also(block: (T) -> Unit): T
    public static T Also<T>(this T self, Action<T> block)
    {
        block(self);
        return self;
    }   
}
Enter fullscreen mode Exit fullscreen mode

Usage

var text = resultCode.Let(x => {
    switch (x) {
        case 0:
            return "success";
        default:
            return $"error({x})";
    }
});

var model = new MyModel().Also(m => {
    m.Initialize();
    m.Load(path);
});
Enter fullscreen mode Exit fullscreen mode

I hope .NET Framework provide these methods.

Top comments (4)

Collapse
 
petergabriel2 profile image
PeterGabriel2 • Edited

Please, didn't you by chance ask Microsoft team when scope functions will be in C#?

C# really need this.

I have hard times to come back from Kotlin to C#. Kotlin is just so much more effective language.

I also miss keyword "val". It's just so elegant. And I would discard keyword "new".

Collapse
 
moljac profile image
moljac

And after your suggestions are accepted and implemented the language will be called k# (keesharp, kosharp).

Why not suggesting here: github.com/dotnet/csharplang

I want multiple inheritance and templates like in C++ with specializations.

Collapse
 
solidogen profile image
Pat B.

Those need to be fixed for folks trying to use them in Unity. It doesn't work well with Unity Objects, as generics erase their overridden equality check.

?. operator doesn't care about overridden equals
blogs.unity3d.com/2014/05/16/custo...

Working ones:

public static void Run<T>(this T self, Action<T> block)
{
    /* 
        Check if Unity Object was destroyed.
        "Destroyed" T as C# object is not null, but as UnityEngine.Object it will be null because of Equals override.
     */
    if ((UnityEngine.Object)(object)self == null)
    {
        return;
    }
    block(self);
}

public static R Let<T, R>(this T self, Func<T, R> block)
{
    /* 
        Check if Unity Object was destroyed.
        "Destroyed" T as C# object is not null, but as UnityEngine.Object it will be null because of Equals override.
     */
    if ((UnityEngine.Object)(object)self == null)
    {
        return default;
    }
    return block(self);
}

public static T Also<T>(this T self, Action<T> block)
{
    /* 
        Check if Unity Object was destroyed.
        "Destroyed" T as C# object is not null, but as UnityEngine.Object it will be null because of Equals override.
     */
    if ((UnityEngine.Object)(object)self == null)
    {
        return default;
    }
    block(self);
    return self;
}
Enter fullscreen mode Exit fullscreen mode

Now it is possible to safely call gameObject?.Run(...) without MissingReferenceException

Collapse
 
moljac profile image
moljac

Nice. Thanks