In C++, you could write the following code:
int Animal::*pAge= &Animal::age;
Animal a;
a.*pAge = 50;
Is there similar functionality in C#?
Edit: To clarify, I am not asking about pointers. I am asking about "pointers to members", a feature found in C++ that is used with the .*
and ->*
operators.
Edit 2: Here is an example of a use case for members to pointers.
Let's say we have the following class:
class Animal
{
int age;
int height;
int weight;
…
}
And let's say that we want to write methods that will find the average age/height/weight/etc. of all Animals in an array. We could then do this:
int averageAge(Animal[] animals)
{
double average = 0;
for (…)
average += animals[i].age;
return average/animals.length;
}
int averageHeight(Animal[] animals)
{
//code here again
}
int averageWeight(Animal[] animals)
{
//code here again
}
We would end up copying and pasting a lot of code here, and if our algorithm for finding the average changed, we would encounter a maintenance nightmare. Thus, we want an abstraction of this process for any member. Consider something like this:
int averageAttribute(Animal[] animals, Func<Animal, int> getter)
{
double average = 0;
for (…)
average += getter(animals[i]);
return average/animals.length;
}
which we could then call with
averageAttribute(animals, (animal) => animal.age);
or something similar. However, using delegates is slower than it has to be; we are using an entire function just to return the value at a certain location in the Animal
struct. In C++, members to pointers allow you to do pointer math (not the right term but I can't think of a better term) on structs. Just as you can say
int p_fourthAnimal = 3;
(animals + p_fourthAnimal)*
to get the value so many bytes ahead of the pointer stored in the variable animals
, in C++, you could say
int Animal::* p_age = &Animal::age;
animal.*p_age //(animal + [the appropriate offset])*
to get the value so many bytes ahead of the pointer stored in the variable animal
; conceptually, the compiler will turn animal.*p_age
into (animal + [the appropriate offset])*
. Thus, we could declare our averageAttribute
as this instead:
int averageAttribute(Animal[] animals, Animal::* member)
{
double average = 0;
for (…)
average += animals[i].*member; //(animals[i] + [offset])*
return average/animals.length;
}
which we could then call with
averageAttribute(animals, &Animal::age);
In summary, pointers to members allow you to abstract a method such as our averageAttribute
to all members of a struct without having to copy and paste code. While a delegate can achieve the same functionality, it is a rather inefficient way to get a member of a struct if you know you do not actually need the freedom allotted to you by a function, and there could even be edge use cases in which a delegate does not suffice, but I could not give any examples of such use cases. Does C# have similar functionality?
As other people have commented here, delegates are the way to achieve this in C#.
While a delegate can achieve the same functionality, it is a rather inefficient way to get a member of a struct if you know you do not actually need the freedom allotted to you by a function
It depends how the compiler and runtime implement that delegate. They could very well see that this is a trivial function and optimize the call away, like they do for trivial getters and setters. In F# for instance you can achieve this:
type Animal = { Age : int }
let getAge (animal:Animal) =
animal.Age
let inline average (prop:Animal->int) (animals:Animal[]) =
let mutable avg = 0.
for animal in animals do
avg <- avg + float(prop(animal)) // no function call in the assembly here when calling averageAge
avg / (float(animals.Length))
let averageAge = average getAge