Is there a C# equivilent to the pointer to member operator?

  • Thread starter Thread starter rellik
  • Start date Start date
R

rellik

Hi All,

Is there a C# version of the C++ pointer (or reference) to member operator -
..* or ->*

Basically I'd like to write a function that can take an object and an offset
to a member of the object to access. For example in the search function
below I'd like to pass in an offset to the member I'd would like to compare
against (in this case _ForeName), meaning I wouldn't have to write a new
function for each member.

struct Person
{
public string _ForeName;
public string _MiddleName ;
public string _Surname ;
}

bool Search(List<Person> arr, string strSearch)
{
foreach(Person person in arr)
{
if(person._ForeName==strSearch) return true ;
}
return false ;
}

Thanks,

-Liam
 
Why not just use a string array? To make the code more readable you could use
an enum type to index the array...

EvilRix.
Hi All,

Is there a C# version of the C++ pointer (or reference) to member
operator - .* or ->*
<snip>
 
rellik said:
Is there a C# version of the C++ pointer (or reference) to member
operator - .* or ->*

Basically I'd like to write a function that can take an object and an
offset to a member of the object to access. For example in the search
function below I'd like to pass in an offset to the member I'd would
like to compare against (in this case _ForeName), meaning I wouldn't
have to write a new function for each member.

Normally, you have no guarantee as to the memory layout of a struct. You
can use [StructLayout] to force a memory layout (LayoutKind.Explicit),
but this might not be the most efficient in terms of memory access.

In the past you could use reflection and guarantee that the members
would be in the same order everytime the code is run, but apparently
with .NET 2.0 this is no longer the case. If you use LayoutKindExplicit
and use [FieldOffset] on members, then you can use reflection
(FieldInfo.GetCustomAttributes) to get the FieldOffsetAttribute and test
the Value to see if it is the offset that you require. Not the best
solution.

Richard
 
Richard Grimes said:
rellik wrote:

Normally, you have no guarantee as to the memory layout of a struct. You
can use [StructLayout] to force a memory layout (LayoutKind.Explicit), but
this might not be the most efficient in terms of memory access.

In the past you could use reflection and guarantee that the members would
be in the same order everytime the code is run, but apparently with .NET
2.0 this is no longer the case. If you use LayoutKindExplicit and use
[FieldOffset] on members, then you can use reflection
(FieldInfo.GetCustomAttributes) to get the FieldOffsetAttribute and test
the Value to see if it is the offset that you require. Not the best
solution.

Richard
--

Thanks Richard, that's most informative. While on balance C# is an great
language, coming from C++ I keep finding restrictions upon the way I would
normally engineer a solution. In this case I may just write a few versions
of the same function as performance will be an issue.

-Liam
 
rellik said:
rellik wrote:

Normally, you have no guarantee as to the memory layout of a struct. You
can use [StructLayout] to force a memory layout (LayoutKind.Explicit), but
this might not be the most efficient in terms of memory access.

In the past you could use reflection and guarantee that the members would
be in the same order everytime the code is run, but apparently with .NET
2.0 this is no longer the case. If you use LayoutKindExplicit and use
[FieldOffset] on members, then you can use reflection
(FieldInfo.GetCustomAttributes) to get the FieldOffsetAttribute and test
the Value to see if it is the offset that you require. Not the best
solution.

Richard
--


Thanks Richard, that's most informative. While on balance C# is an great
language, coming from C++ I keep finding restrictions upon the way I would
normally engineer a solution. In this case I may just write a few versions
of the same function as performance will be an issue.

-Liam
There is no need to write the same function all over again. You can use
List<T>.Find and just rewrite the functor:

class MatchByForeName
{
public static Predicate<Person> Create(string foreName)
{
return (new MatchByForeName(foreName)).Match;
}
private MatchByForeName(string foreName)
{
this.forename = foreName;
}
private bool Match(Person p)
{
return p._ForeName == forename;
}
string forename = string.Empty;
}

//
Person p = arr.Find(MatchByForeName.Create(strSearch));


HTH,
Andy
 
There is no need to write the same function all over again. You can use
List<T>.Find and just rewrite the functor:
Hi Andy,

There's been a misunderstanding - it's probably my fault but my problem had
nothing to do with string compares, it was just the simplest example that
came to mind. I was after a generic pointer to member facility it C#. It
appears there is none.

After giving it some though I've decided to use generics and anonymous
delegates and I am quite happy with it. Here's some sample code.

public bool DoIt(Person p,GetPtrMember<string,Person> getVal)

{

return getVal(p)=="hello";

}

private void button1_Click(object sender, EventArgs e)

{

Person p = new Person();

bool bRet = DoIt(p, new GetPtrMember<string,Person>(delegate(Person pIn) {
return pIn._strForename; }));

}

public delegate Ret GetPtrMember<Ret,Typ>(Typ a) ;

public class Person

{

public string _strForename="hello";

public string _strSurname="world";

}



There are a number of flaws in this approach. 1. Performance, 2. The member
has to be public or have a public property.

Still, it'll do for now.



-Liam
 
Richard Grimes said:
rellik said:
Is there a C# version of the C++ pointer (or reference) to member
operator - .* or ->*

Basically I'd like to write a function that can take an object and an
offset to a member of the object to access. For example in the search
function below I'd like to pass in an offset to the member I'd would
like to compare against (in this case _ForeName), meaning I wouldn't
have to write a new function for each member.

Normally, you have no guarantee as to the memory layout of a struct. You
can use [StructLayout] to force a memory layout (LayoutKind.Explicit), but
this might not be the most efficient in terms of memory access.


In the past you could use reflection and guarantee that the members would
be in the same order everytime the code is run, but apparently with .NET
2.0 this is no longer the case.

Where did you get this from?
As far as I know the struct (value type) lay-out is still guaranteed to be
arranged in the order as specified in the definition, provided one the
StructLayoutAttribute.Sequential or StructLayoutAttribute.Explicit is
applied.

Willy.
 
rellik said:
Thanks Richard, that's most informative. While on balance C# is an great
language, coming from C++ I keep finding restrictions upon the way I would
normally engineer a solution. In this case I may just write a few versions
of the same function as performance will be an issue.

Yes, C# is a different language with different idioms. If you find that
C# is "resisting" the solution you'd use in C++, that's usually a sign
that it's not the best way to accomplish the larger goal in C#. It's
definitely not worth trying to force C# into a C++-like shape :)

Depending on exactly what you need to do, you could write three methods
which take List<Person> return Enumerator<string>, then use those in
various places wherever you wanted to write a general method like
Search.
 
rellik said:
Hi Andy,

There's been a misunderstanding - it's probably my fault but my problem had
nothing to do with string compares, it was just the simplest example that
came to mind. I was after a generic pointer to member facility it C#. It
appears there is none.

After giving it some though I've decided to use generics and anonymous
delegates and I am quite happy with it. Here's some sample code.

public bool DoIt(Person p,GetPtrMember<string,Person> getVal)

{

return getVal(p)=="hello";

}

private void button1_Click(object sender, EventArgs e)

{

Person p = new Person();

bool bRet = DoIt(p, new GetPtrMember<string,Person>(delegate(Person pIn) {
return pIn._strForename; }));

}

public delegate Ret GetPtrMember<Ret,Typ>(Typ a) ;

public class Person

{

public string _strForename="hello";

public string _strSurname="world";

}



There are a number of flaws in this approach. 1. Performance, 2. The member
has to be public or have a public property.

Still, it'll do for now.



-Liam
Hi Liam,
sorry for my my bad explanation. I basically meant the same thing that
you outlined in you code. My point was that you just have to rewrite the
access to the field and encapsulate it into an object and that a lot of
collections now have basic algorithms taking such functors.

on (1)
From my experience, your solution should perform extremely fast. As I
use a similar technique in a performance critical section of my project
I'm interested where you are having problems.

on (2): the member has to be accessible, not necessary public: Make the
field private. Then you can provide a property in two ways:
-An internal property.
-Define the properties in an interface. Let you other methods operate on
the interface and the Person class implements the interface *explicitly*.

HTH,
Andy
 
Andreas Mueller said:
rellik wrote:
Hi Liam,
sorry for my my bad explanation. I basically meant the same thing that you
outlined in you code. My point was that you just have to rewrite the
access to the field and encapsulate it into an object and that a lot of
collections now have basic algorithms taking such functors.

on (1)
From my experience, your solution should perform extremely fast. As I use
a similar technique in a performance critical section of my project I'm
interested where you are having problems.

I tested it today and was indeed quite happy with the performance. Obviously
not as fast as a native c++ version with a simple offset but more than
adequate for the job in hand.
on (2): the member has to be accessible, not necessary public: Make the
field private. Then you can provide a property in two ways:
-An internal property.
-Define the properties in an interface. Let you other methods operate on
the interface and the Person class implements the interface *explicitly*.

Cheers Andy, I implemented your suggestion and am now more than happy with
the results.

-Liam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top