Reputation: 19093
I need to call a function for an object of a certain type, but I want the caller to specify which function I call.
In C++ I can use pointer to member like this:
Type (Properties::* getType1)() = &Properties::GetType1;
Is there any C# equivalent?
No arrays of function or any tricks like switches please. I want this solution to work even if a new function is added while function signature meets the requirements.
EDIT: As i have read: Delegates are like C++ function pointers but are type safe.
But i need member function pointer. E.g. in my function i acquire certaint object:
var properties = manager.GetProperties();
and now need to get certain type of properties:
var type1 = properties.GetType1();
but i need something like this
var typeX = properties.GetTypeX();
to get user requested type for this function call. What must TypeX be?
Where Type1..N have common base class, and I need to work with this class.
Upvotes: 1
Views: 1812
Reputation: 12465
The other answers don't give the full answer if you are looking for the equivalent of the pointer to member operator from C++.
In C++ you can take a pointer to a member (either a field or method, in the OP's question it was a method) and then apply it to any instance of the class that defines that member to call the method or retrieve the field on that instance. These include virtual and non-virtual functions (which is cleverer than it first appears).
Delegates are more like straight function pointers (when used with static functions as per the other answers here) or closures (think std::function) when used to capture local state (possibly including a specific this pointer). That's not to say that delegates aren't part of the answer, but only when used in a specific way not yet detailed elsewhere.
There are four possible answers to the question of how to actually simulate pointer to members in C#:
Delegates from the object type that call the required member. (I use lambdas to define them, which may not have been available at the time of asking the question but with a bit more code the same thing could have been done by defining these as separate functions.)
Func<Properties, Type> getType1 = properties => properties.GetType1();
Func<Properties, Type> getType2 = properties => properties.GetType2();
getType1(properties);
Reflection.
MethodInfo getType1 = properties.GetType().GetMethod("GetType1");
MethodInfo getType2 = properties.GetType().GetMethod("GetType2");
getType1.Invoke(properties, null);
Expressions. These are like delegates except that they open up alternative ways of creating the expressions or inspecting them (e.g. to ensure that they are simple method calls). (These may not have been available at the time of the original question.)
Expression<Func<Properties, Type>> getType1 = properties => properties.GetType1();
Expression<Func<Properties, Type>> getType2 = properties => properties.GetType2();
getType1.Compile().Invoke(properties);
It can't be done.
In C++ the pointer to member is very efficient as it uses the offset of the member in the object's structure. None of the above mechanisms exactly simulate that approach or match that efficiency. The delegates (and thus the expressions once compiled) come close but they wrap the call inside another function meaning there are two function calls where in C++ there would be one.
Hopefully this is a more complete answer to the original question.
Upvotes: 0
Reputation: 19
In C# there are delegates to specify signature of function which you want to pass somewhere.
Your code should try something like that:
class Program
{
static void Write(int i)
{
Console.Write(i);
}
static void Main(string[] args)
{
C c = new C { FunctionToExecute = Write };
c.SomeMethod(5);
}
}
delegate void D(int F);
class C
{
public D FunctionToExecute { get; set; }
public void SomeMethod(int arg)
{
FunctionToExecute(arg);
}
}
D specifies signature, FunctionToExecute is pointer to what you want to execute.
If you want to pass objects of unknown types then there are generics. Or I don't understand exactly what do you want. Mentioned here Action and Func are generic delegates.
Upvotes: 1