'References' (pointers) in C# (without using unsafe)

  • Thread starter Thread starter _ed_
  • Start date Start date
E

_ed_

I'd like to build a class or struct composed of pointers to variables.
Does this require dropping into an 'unsafe' block, or is there a
trick?

....
int value1 = 1234;
bool value2 = false;
string value3 = "Hello Detroit";

public class x {
int *adr_value1 = &value1;
bool *adr_value2 = &value2;
string *adr_value3 = &value3;
}
 
I'd like to build a class or struct composed of pointers to variables.
Does this require dropping into an 'unsafe' block, or is there a
trick?

....
int value1 = 1234;
bool value2 = false;
string value3 = "Hello Detroit";

public class x {
int *adr_value1 = &value1;
bool *adr_value2 = &value2;
string *adr_value3 = &value3;
}

Why exactly do you feel you need pointers? What's wrong with
references for what you intend?

/Magnus Lidbom
 
Why exactly do you feel you need pointers? What's wrong with
references for what you intend?

/Magnus Lidbom

Changing 'adr_value1' needs to change 'value_1'.
It needs to react like a pointer for any data type--
not just an object.
 
_ed_ said:
Changing 'adr_value1' needs to change 'value_1'.
I assume you mean changing *adr_value1.

Most likely you do not need to use pointers, but without more
information I can't say for sure. For instance, those variables are
just hanging there in the air. Are they class fields? struct fields?
I'm thinking you can most likely wrap them in a class and keep a
reference to an instance of that class around.
It needs to react like a pointer for any data type--
not just an object.
You can forget about that I'm afraid. From the language spec:

<specification>
Unlike references (values of reference types), pointers are not
tracked by the garbage collector - the garbage collector has no
knowledge of pointers and the data to which they point. For this
reason a pointer is not permitted to point to a reference or to a
struct that contains references, and the referent type of a pointer
must be an unmanaged-type.

An unmanaged-type is any type that isn't a reference-type and doesn't
contain reference-type fields at any level of nesting. In other words,
an unmanaged-type is one of the following:

sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
double, decimal, or bool.
</specification>


/Magnus Lidbom
 
I assume you mean changing *adr_value1.

Most likely you do not need to use pointers, but without more
information I can't say for sure. For instance, those variables are
just hanging there in the air. Are they class fields? struct fields?
I'm thinking you can most likely wrap them in a class and keep a
reference to an instance of that class around.

You can forget about that I'm afraid. From the language spec:

<specification>
Unlike references (values of reference types), pointers are not
tracked by the garbage collector - the garbage collector has no
knowledge of pointers and the data to which they point. For this
reason a pointer is not permitted to point to a reference or to a
struct that contains references, and the referent type of a pointer
must be an unmanaged-type.

An unmanaged-type is any type that isn't a reference-type and doesn't
contain reference-type fields at any level of nesting. In other words,
an unmanaged-type is one of the following:

sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
double, decimal, or bool.
</specification>

oops. I lost a bit of that quote. The list of types should have been
like this:

sbyte, byte, short, ushort, int, uint, long, ulong, char, float,
double, decimal, or bool.
Any enum-type.
Any pointer-type.
Any user-defined struct-type that contains fields of unmanaged-types
only.

/Magnus Lidbom
 
I assume you mean changing *adr_value1.

Yes, I mixed C# and C++ syntax. I retrofitted some C++isms to the
original post to try to clarify what I was after. I guess that didn't
work said:
Most likely you do not need to use pointers, but without more
information I can't say for sure. For instance, those variables are
just hanging there in the air. Are they class fields? struct fields?
I'm thinking you can most likely wrap them in a class and keep a
reference to an instance of that class around.

Specifically, I need to maintain a (class) object that contains vars
of different types:

public class LocalVars {
int x;
bool y;
string z;
}

But I need to set those values from a file, and enter defaults if the
value is not found or if it's not 'legal'. The file is text, so all
the values are parsed from key/value pairs.

So... There are three things to deal with for each item:
The variable itself, the (text) key, and the default value.

In the course of generating inline code to do this, I realized that I
could just create a generalized function to loop over all the values,
but I'd need to bundle those three values together:

class or array {
{ int *xptr; string xkey; int xdefault; }
{ bool *yptr; string ykey; bool ydefault; }
}

(Simplified cause I'm trying to be brief)

So that's why I'd need to pass pointers to the original values.
I'm still thinking about this, maybe too much in C++ mindset. There
may be a simpler way of achieving the same result.
 
Yes, I mixed C# and C++ syntax. I retrofitted some C++isms to the
original post to try to clarify what I was after. I guess that didn't


Specifically, I need to maintain a (class) object that contains vars
of different types:

public class LocalVars {
int x;
bool y;
string z;
}

But I need to set those values from a file, and enter defaults if the
value is not found or if it's not 'legal'. The file is text, so all
the values are parsed from key/value pairs.

So... There are three things to deal with for each item:
The variable itself, the (text) key, and the default value.

In the course of generating inline code to do this, I realized that I
could just create a generalized function to loop over all the values,
but I'd need to bundle those three values together:

class or array {
{ int *xptr; string xkey; int xdefault; }
{ bool *yptr; string ykey; bool ydefault; }
}

(Simplified cause I'm trying to be brief)

So that's why I'd need to pass pointers to the original values.
I'm still thinking about this, maybe too much in C++ mindset. There
may be a simpler way of achieving the same result.

I find it very unlikely that there would be a good reason for going
unsafe to perform such a task. Based on a whole lot of guesses, how
about this as a base algorithm?

class FileReader
{
static Hashtable defaults;
static FileReader()
{
defaults = new Hashtable();
defaults["VarName1"] = 3;
defaults["VarName2"] = 4;
}

static bool ValidValue(int value)
{
return value > 0 && value < 500;
}

public static Hashtable FileValues()
{
Hashtable values = new Hashtable();
string[] rowsFromFile = new string[]{"VarName1,-1",

"VarName2,2"};
foreach(string row in rowsFromFile)
{
string[] pair = row.Split(',');
string key = pair[0].Trim();
int value = int.Parse(pair[1]);
values[key] = ValidValue(value) ? value : defaults[key];
Console.WriteLine("Assigned the variable {0} the value {1}" ,
key, values[key]);
}
return values;
}
}

That can probably be done a whole lot more elegantly, but unless i
misunderstand your requirements it should work just fine.

/Magnus Lidbom
 
class FileReader
{
static Hashtable defaults;
static FileReader()
{
defaults = new Hashtable();
defaults["VarName1"] = 3;
defaults["VarName2"] = 4;
}

static bool ValidValue(int value)
{
return value > 0 && value < 500;
}

public static Hashtable FileValues()
{
Hashtable values = new Hashtable();
string[] rowsFromFile = new string[]{"VarName1,-1",

"VarName2,2"};
foreach(string row in rowsFromFile)
{
string[] pair = row.Split(',');
string key = pair[0].Trim();
int value = int.Parse(pair[1]);
values[key] = ValidValue(value) ? value : defaults[key];
Console.WriteLine("Assigned the variable {0} the value {1}" ,
key, values[key]);
}
return values;
}
}

That can probably be done a whole lot more elegantly, but unless i
misunderstand your requirements it should work just fine.

/Magnus Lidbom


Very nice, Magnus! I will have to look at it a bit closer, but the
use of hash tables seems a good idea.

Thanks!
 
Back
Top