Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function to return a function that returns a function, etc

Tags:

c#

Is it possible to define a function in a way that it basically returns itself as a delegate?

For example, if this was valid syntax:

public class Scrub
{
    public NotNull NotNull<T>(T value, string name)
    {
        if (value == null) throw new ArgumentNullException(name);
        return NotNull; 
    }
}

Then I could chain method calls together like this.

Scrub.NotNull(param1, nameof(param1))(param2, nameof(param2)(param3, nameof(param3));
like image 593
adam0101 Avatar asked Aug 02 '16 21:08

adam0101


2 Answers

Well yes, you can, with your own delegate declaration:

delegate SelfReturner<T> SelfReturner<T>(T value, string name);

static SelfReturner<T> NotNull<T>(T value, string name)
{
    if (value == null) throw new ArgumentNullException(name);
    return NotNull;
}

... but it doesn't seem useful to me. Any reason you really want to do this, rather than just making three separate calls? For example, I have a Preconditions.CheckNotNull which returns the non-null value - I find that a lot more useful than this looks, to be honest.

As noted in comments, the above only works if all the parameters are of the same type (or all implicitly convertible to the type of the first parameter). An alternative to allow chaining with a bit more work would be to use a singleton instance with a generic method:

public sealed class NullChecker
{
    public static NullChecker Instance { get; } = new NullChecker();
    private NullChecker() {}

    public static NullChecker Scrub<T>(T value, string paramName) where T : class
    {
        if (value == null)
        {
            throw new ArgumentNullException(paramName);
        }
        return this;
    }
}

Use as:

NullChecker.Instance.Scrub(param1, nameof(param1))
                    .Scrub(param2, nameof(param2))
                    .Scrub(param3, nameof(param3));

With two separate methods, one static and one not (but with different names) you could remove the Instance part. For example:

NullChecker.Scrub(param1, nameof(param1))
           .And(param2, nameof(param2))
           .And(param3, nameof(param3));
like image 87
Jon Skeet Avatar answered Oct 22 '22 12:10

Jon Skeet


If you make it an extension method:

public static class Scrub
{
    public static T NotNull<T, U>(this T value, U property, string name)
    {
        if (property == null) throw new ArgumentNullException(name);
        return value;
    }
}

You can do:

test.NotNull(test.A, nameof(testA.A).NotNull(test.B, nameof(testA.B)));

Not quite what you wanted.

like image 23
Ian Mercer Avatar answered Oct 22 '22 12:10

Ian Mercer