Saket Kumar
Saket Kumar

Reputation: 4835

Can I access delegate inside another delegate of same class?

I don't know if my understanding is wrong, but I am trying to do something like below:

I have a base class with two delegates:

 public class Base
 {
     public Func<bool> Licensed { get; set; }
     public Func<bool> Enabled { get; set; }
 }    

And a derived class as shown below:

public class Derived : Base
{
    public int Test { get; set; }
}

Now, I am trying to instantiate derived class in Main():

static void Main(string[] args)
{
    Derived obj = new Derived()
    {
        Licensed = () => { return true; },
        Enabled = () => { return Licensed() && true; }, //access above delegate
     };
}

The thing is in Enabled implementation, I want to access Licensed delegate assigned just above. I am not able to achieve this as it is not allowed. Is this doable in some other way?

Upvotes: 2

Views: 385

Answers (2)

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

Note: I provide this answer to show some other approach to the OP to solve the problem. I won't try to say no, you can't with a full explanation since this has been already answered by @SergeyBerezovskiy.

Another option could be turning this into a fluent API.

When I need to set delegates I tend to think that they should be set once, never changed. Therefore, properties holding those delegates should be publicly readable and privately settable.

In the other hand, a fluently-configured object should be created using a factory method and its constructor will be private.

Finally, each method on the fluent chain should also inject the instance being configured, while you'll end up setting a delegate which calls the one passed as argument to the configuration methods.

That is, you got what you want in a very elegant way.

public class Derived : Base
{
     private Derived() {}

     public static Derived Create() => new Derived();

     public Func<bool> Licensed { get; private set; }
     public Func<bool> Enabled { get; private set; }

     public void LicensedIf(Func<Derived, bool> licensingCondition)
            => Licensed = () => licensingCondition(this);

     public void EnabledIf(Func<Derived, bool> enablingCondition)
            => Enabled = () => enablingCondition(this);
}

// Fluent configuration of your *licensable object* gets self-documented
// by the usage!
// Oh, and see how EnableIf() takes advantage of C#6's null conditional
// operator to invoke the "Licensed" delegate if its really set. This is
// so safe!
var derived = Derived.Create().LicenseIf(d => true)
                              .EnableIf(d => d.Licensed?.Invoke() && true);

That thing of encapsulating a delegate inside delegate would be called currying in functional programming! See What is 'Currying'? if you're interested in this topic.

Upvotes: 2

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236248

You cannot reference other properties in object initializer. C# Language Specification 7.6.10.2 Object initializers:

It is not possible for the object initializer to refer to the newly created object it is initializing.

But you can use old-fashioned property assignment:

var obj = new Derived { Licensed = () => true; };
obj.Enabled = () => obj.Licensed() && true;

Upvotes: 4

Related Questions