I am trying to learn some c# coding and wondering if the c++ concept of function pointers is included in c#. I see there are such things as delegates. Are they the same concept? or do they differ on a more fundamental level?
Delegates are essentially function pointers, but with extra multicast capabilities built in. So you can assign several functions to the same delegate, and they will all be called in sequence when the delegate is called.
Delegates also have built-in asynchronous interfaces, and have co/contra variance when assigning new functions to a delegate (and, in .NET 4, when passing delegates around)
As others have said, you'll want to use delegates for situations in C# that you would have used function pointers for in C++. Delegates are conceptually similar to function pointers but far more pleasant to use, since they encapsulate not just the function, but also the "receiving" object which will be the "this" of the invocation.
Note that the CLR does have the concept of function pointers. If you were to take a close look at how the C# compiler generates code that constructs delegates, you'd see that it makes a managed reference to a function and passes that to a delegate constructor. There is no language feature in C# that allows you to get at the "naked" function pointer and manipulate it directly.
However, since the concept does exist in the CLR, it is theoretically possible that a future version of C# could support function pointers as a first-class concept in unsafe code, just as we support data pointers in unsafe code. What we would do in that case is (1) track the signature of the function pointer as the pointer type, and (2) emit code that uses the "calli" (call through pointer indirection) CIL opcode.
This would increase efficiency in certain obscure interop scenarios where today basically you have to make the marshalling code jump through a lot of hoops, building up delegate instances solely so that the marshaller can get at the function pointer stored in them. If we could avoid requiring the expense of delegate construction and go straight to the function pointer then those now-rare interop scenarios could become less expensive.
However, I wouldn't hold my breath waiting for that feature if I were you. We've prototyped it and it works reasonably well, but I don't think the demand is there to warrant adding it to a general-purpose language like C# at this time.
Delegates are essentially function pointers, but with extra multicast capabilities built in. So you can assign several functions to the same delegate, and they will all be called in sequence when the delegate is called.
Delegates also have built-in asynchronous interfaces, and have co/contra variance when assigning new functions to a delegate (and, in .NET 4, when passing delegates around)
Not in the classical C/C++ sense, no. But the concept is somewhat similar - .NET introduces the concept of delegates to handle situations where you need a variable to invoke a method upon. Delegates cannot be "twiddled" with as pointers can and there is type safety built-in.
If you use C-style function pointers "correctly" the concepts are similar. But there seems to be a lot of legacy code which does funny manipulations of the pointers to skirt around type-safety or what-not.
A delegate is similar to a function pointer in some ways, but actually it is closer to an interface with only one function combined with a way to register handlers and a multicast dispatching mechanism.
So it's a lot more than a function pointer.
C# does have something like a function pointer, which is call delegate. Well... I can't really give you a theoretical answer to the difference between them. But I can give you a difference in code implementation between C# delegate vs C++ function pointers.
C#
delegate void voidFn();
voidFn fnDel;
List<int> intList = new List<int>();
fnDel = intList.Clear
This would compile in c# easily.
C++
typedef void (*voidFn)();
voidFn fnDel;
std::vector<int> intList;
fnDel = intList.clear;
Nope... I am sorry to tell you that in c++ this will not work, even though logically speaking, it felt like the vector's clear function is the same as a void fn(). We don't simply point to an address of the vector's function and say, "Hey! let's clear this vector at this callback" I hope someone can reply a more concrete explanation to this, but I am guessing it got something to do with not knowing which vector to look for.
However, with a little bit of polymorphism... we can transfer something like a C# delegate around...
#include <iostream>
#include <vector>
class A
{
public:
A() {}
virtual void operator()() { std::cout << "A is called"; }
};
class B : A
{
public:
B(std::vector<int>& vec):vec_(vec){}
void operator()() { vec_.clear(); std::cout << "B is called" << std::endl; }
private:
std::vector<int>& vec_;
};
int main()
{
std::vector<int> tmpVec;
for (int i = 0; i < 10; ++i)
{
tmpVec.push_back(i);
}
B* b = new B(tmpVec);
A* a = (A*)b;
std::cout << "Current vec size: " << tmpVec.size() << std::endl;
(*a)();
std::cout << "Current vec size: " << tmpVec.size() << std::endl;
delete b;
return 0;
}
Yup.. that's right... with the help of functors and a little inheritance with their virtual function thingy, we can actually have a form of "delegate void VoidFn()" in Class A. The above code would run class B because of how inheritance work, and will clear 'tmpVec' for us.. So YIPPEE, we can write a pretty flexible C++ callback that doesn't rely on a 'unflexible' function pointer after all!
In addition to the answer of N00bKefka I have to let you know that there are member function pointers in C++ and there is no need to define any new class at all.
Here is how to point at intList.clear
, where intList
is an instance of std::vector<int>
, and then invoke that function without defining any new class at all:
typedef void(std::vector<int>::*voidFn)(); //voidFn is now the type of all pointers to std::vector<int> functions
voidFn fnDel; //fnDel is now an instance of voidFn which was defined above.
std::vector<int> intList; //intList is now an instance of std::vector<int>
fnDel = &std::vector<int>::clear; //fnDel now points at std::vector<int>::clear.
((intList).*(fnDel))(); //Invoking intList.clear through fnDel. A macro can greatly simplify this line of code and make it much more readable.
//But since C++17 you just do
std::invoke(fnDel,intList); //Does exactly the same as the previous instruction.
But of course that C# delegates are the best according to all the other answers here.
Starting from C# 9.0, the answer is yes: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/function-pointers
© 2022 - 2024 — McMap. All rights reserved.