简体   繁体   中英

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?

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;

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM