none
Can a non-member (outside) method be invoked as if it were a member? RRS feed

  • Question

  • Hello.

    I'm trying to make an array of methods and a delegate to point to one of them based on conditions.

    At runtime, for the current object, I would normally call a member method but I want the method to be "dynamic", unknown beforehand. That's why I thought of using a delegate.

    Ideally I'd have this array of methods in some static class. The methods would be written as if they were inside a class, with references to member fields and methods.

    The delegate in current object of that class, would point to one of those and the invocation would happen exactly (copy-paste) as if the method were written as a member method, i.e. with references to object's fields.

    Is this possible?

    The catch is, inside those plain "data" methods (or delegates), I'm not allowed to reference fields of an arbitrary object.

    If it's not possible, then what's the best approach?

    EDIT:

    I'd like to avoid reflection because performance is critical.


    Sunday, January 21, 2018 1:06 PM

Answers

  • Maybe you could change the delegates in functionDels so that they are of the form

            delegate(Foo caller) {
                caller.
    bar+=1;
           
    }

    Then you can call them as

            functionDel(this);

    Of course this requires changing the definition of FunctionDelegate to

    public delegate void FunctionDelegate(Foo caller);

    If you want to be able to use multiple classes instead of only Foo, you can define an interface as we mentioned before and use this intead of Foo.

    Monday, January 22, 2018 9:01 PM
    Moderator

All replies

  • You can point a delegate to any method, be it a class member or a static method. The caller of the delegate will not notice any difference.

    If the delegate points to an instance method, it will "capture" the correct instance, so that any time you invoke the method and the method calls a member variable of its class, it will be accessing the variable within the instance to which the method belonged when you created the delegate pointing to the method.

    So, in summary, if I understood correctly what you intended to do, then yes, it will work and it is a good approach.

    By the way, if you finally decide to use Reflection instead of known delegates, don't worry too much about performance. It has a bad fame in this regard, but it actually works quite fast in practice, because it caches the information about the object that you reflected upon the first time that you call it, and then in successive invocations it uses the cached information for quick performance.

    Sunday, January 21, 2018 4:36 PM
    Moderator
  • I miss a little bit or you miss something. 

    What is the difference with simply referencing the method in the normal C# way. 

    The only purpose I see is if I want that my program becomes unmaintainable for others. 

    Therefore, give us the goal that you want to achieve.

    Possible, maybe but should people help others with obscure ways using C#?

     

    Success Cor

    Sunday, January 21, 2018 6:18 PM
  • @Alberto Poblacion @Cor Ligthert:

    I'm trying to make it as clear as I can:

    I'm developing a game in Unity 3D and it has some restrictions regarding C#. I can't use static members. So I'm using separate classes. For instance I have objects of Foo type, containing a Foo_statics singleton.

    In Foo_statics I have an array of delegates:

    public abstract class Foo_statics
    {
        //... (some not read-only public data) ...
    
        public delegate void FunctionDelegate();
        
        public FunctionDelegate[] functionDels = 
        {
            delegate()
            {
                bar+=1; // The name 'bar' doesn't exist in the current context
            },
            
            delegate()
    	{
    	    bar-=1; // The name 'bar' doesn't exist in the current context
    	},
            // ... (another 70-100 delegates) ...
        };
    }
    
    // thousands of Foo objects:
    public class Foo
    {
        public Foo_statics fs;
        public int index;
        
        public bar {get; set;}
        // ... (another properties, fields, methods) ...
        public Foo_statics.FunctionDelegate functionDel;
        
        // called every 2 seconds from outside:
        public void CycleFunctionality()
        {
            index = (index + 1) % fs.functionDels.GetLength();
            functionDel = fs.functionDels[index];
        }
        
        public void DoEvery17ms()
        {
            // ... (other code) ...
            functionDel();
        }
    }
    Problem arises at underlined `bar`. I need to be able to write those methods in the delegate array, as if I were write them directly as members, inside `Foo`, referencing `bar` and other members. I even prefer for now and future projects, that the code inside the delegates to be type agnostic, i.e. wouldn't relate `bar` to any particular class, so I can "hotplug" the delegates to different unrelated classes.




    • Edited by andreiMarianMirea Monday, January 22, 2018 11:59 AM formatting was not preserved
    Monday, January 22, 2018 10:09 AM
  • Given that you are calling fs.functionDels, this means that at some point you need to create an instance of fs, otherwise you wouldn´t be able to reference functionDels. So, when you create the instance, you can define a constructor that refers to the creator: fs = new ChildOfFoo_statics(this). Then the constructor saves the received value in a member variable such as "private Foo parent;". After doing this, your "bar" variable can be referred as "parent.bar".

    The second issue, about being independent of Foo and being able to use other classes that contain "bar", could be solved by defining an interface such as "IBar" that specifies property "bar" and making Foo implement that interface. Then, the argument for the Foo_statistics constructor and the private "parent" variable would be of type IBar. This lets you pass to the constructor any class as long as it implements IBar (which would guarantee that it has a "bar" property).

    Monday, January 22, 2018 4:26 PM
    Moderator
  • Thank you, @Alberto Poblacion. I remind you that `fs` is a singleton of `Foo_statics`, it represents the static part of `Foo`. Plus I want to avoid creating a thousand `functionDels`'s, which would mean 100 * 1000 delegates.
    Monday, January 22, 2018 5:12 PM
  • So, if Foo_statics represents static data, how would you pair this data against the callers? That is, when Foo_statics refers to bar, and you have multiple Foo classes containing bar, how would Foo_statics know which of the "bars" it needs to access? Where would you save the connection between both of them? Wherever you decide to save it, it cannot be static, because you need to save several instances.
    Monday, January 22, 2018 6:18 PM
    Moderator
  • Thanks for still staying with me.

    I tried to present the whole situation in the code, such that one wouldn't need to read anything else at all, but just the code.

    So, I made `fs` -- the "static" part as "inert" as it can be, it's just data. The action happens in `Foo` instances based on the "non-static" `index`.

    Monday, January 22, 2018 7:29 PM
  • Maybe you could change the delegates in functionDels so that they are of the form

            delegate(Foo caller) {
                caller.
    bar+=1;
           
    }

    Then you can call them as

            functionDel(this);

    Of course this requires changing the definition of FunctionDelegate to

    public delegate void FunctionDelegate(Foo caller);

    If you want to be able to use multiple classes instead of only Foo, you can define an interface as we mentioned before and use this intead of Foo.

    Monday, January 22, 2018 9:01 PM
    Moderator
  • This is it! This perfectly fits my case. I don't know how I've missed it. Te lo agradesco, Alberto Poblacion :)
    Monday, January 22, 2018 9:18 PM