Distinguishing between data passed by vale or by ref.

J

Jay Dee

Hi all,

I am slightly confused about an odd result that douse not create an
error, but also douse not give the result I would expect.

My aim was to output data to a text file.

If the data was passed by value, output the name and the data.

If the data was by ref to output just the name as reference to the
data because the data has already bean output previously in the file.

As an example, this code should accept a string by value or ref and
output true or false depending on witch.

// CODE
class TestClass
{
public void Test(string Obj)
{
System.Type Type = Obj.GetType();
if (Type.IsByRef == true)
{ System.Windows.Forms.MessageBox.Show("True"); }
else { System.Windows.Forms.MessageBox.Show("False"); }
}
public void Test(ref string Obj)
{
System.Type Type = Obj.GetType();
if (Type.IsByRef == true)
{ System.Windows.Forms.MessageBox.Show("True"); }
else { System.Windows.Forms.MessageBox.Show("False"); }
}
}
// END

When called with a value then a ref, e.g.

// CODE
string theString = "Data";
TestClass TestClass = new TestClass();
TestClass.Test(theString);
TestClass.Test(ref theString);
// END

I world expect it to display "False" then "True".

However called "false" is always output and I can not understand why.
Am I using the wrong approach or doing something else wrong.

Thank you in advance for any suggestions.
 
J

Jon Skeet [C# MVP]

I am slightly confused about an odd result that douse not create an
error, but also douse not give the result I would expect.

My aim was to output data to a text file.

If the data was passed by value, output the name and the data.

If the data was by ref to output just the name as reference to the
data because the data has already bean output previously in the file.

As an example, this code should accept a string by value or ref and
output true or false depending on witch.

You're looking at the type of the object, and that will be the same
whether the *parameter* has been passed by reference or by value. The
type of the object is unchanged by how the parameter has been passed,
which is why you're getting the same answer in both ways.

Is this the only reason why you're using "ref" or not? If so, I'd just
pass a boolean instead.

Anyway, here's some code which does what you want it to, by examining
the method with reflection:

using System;
using System.Reflection;

public class Test
{
static void Main()
{
string x = "";
ByVal(x);
ByRef(ref x);
}

static void ByVal(string x)
{
ShowFirstParameterType(MethodBase.GetCurrentMethod());
}

static void ByRef(ref string x)
{
ShowFirstParameterType(MethodBase.GetCurrentMethod());
}

static void ShowFirstParameterType(MethodBase method)
{
ParameterInfo[] pi = method.GetParameters();
Console.WriteLine(pi[0].ParameterType.IsByRef);
}
}

Jon
 
P

Peter Duniho

Jay said:
Hi all,

I am slightly confused about an odd result that douse not create an
error, but also douse not give the result I would expect.

My aim was to output data to a text file.

If the data was passed by value, output the name and the data.

If the data was by ref to output just the name as reference to the
data because the data has already bean output previously in the file.

Maybe you could be more explicit about this actual goal. Nothing in the
code you posted appears to be writing to a text file, but if that's all
you're trying to do it's likely that you're barking up the wrong tree.
You shouldn't have to do anything with reflection to do that.

That said, as far as the specific code you did post goes...
As an example, this code should accept a string by value or ref and
output true or false depending on witch.

The Type.IsByRef property doesn't do what you seem to think it does.
It's a property of a specific kind of _Type_, not a specific parameter.
If you had a type was an actual reference (e.g. "Int32&"), then it
would return "true". But your parameter isn't actually a ByRef type.
It's passed by reference, but the type is just "String", not "String&".

Personally, I find it confusing too. But it's probably because I don't
fully understand how C# handles the "ref" keyword. It does seem clear
to me from the behavior though that even though the parameter is passed
by reference, the parameter itself is not a ByRef type. The
documentation suggests that one place you'd actually use a ByRef type is
in the use of Reflection to emit code that has ByRef parameters.

So in other words, you'd only ever see the ByRef type in a method
signature, not in the code inside the method itself.

Maybe someone who knows more about the Reflection stuff will chime in
and explain why there's this difference between the parameter type in
the method signature and the parameter's type itself.

As I mentioned, it's not really clear what you're really trying to
accomplish here. But I suspect whatever it is, you don't need this
Reflection business. If you could try to make more clear what the
actual ultimate goal here is, perhaps some alternative suggestions could
be made.

Pete
 
J

Jay Dee

Sorry for not explaining the problem very well and thank you for the
answers.

The reason for starting the project was that Model building software
like Blender and AC3D, though useful were not built specifically for
the DirectX format and each have limitations and I though it would be
a challenge to build my own.

I am fairly new to programming and wanted to learn the basics of
storing and manipulating data.

Sins binary looked a bit to complicated I started with text files.

The DirectX format saves data as txt to a .x file and looked a good
place to start so I have built a DLL that reads the data from a .x
file and populates arrays that can be used to display 3D models.

Then when it can to saving the data back the file I became stuck
because it was repeating the data rather than making a reference to
it.

E.g.

Material Material1
{
1.0; 1.0; 1.0; 1.0;;
64.0;
0.5; 0.5; 0.5;;
0.0; 0.0; 0.0;;
TextureFileName { "Image.png"; }
}

Mesh MyMesh
{
MeshMaterialList
{
1;
{ Material1 }
}
}

Was being output as:

Material Material1
{
1.0; 1.0; 1.0; 1.0;;
64.0;
0.5; 0.5; 0.5;;
0.0; 0.0; 0.0;;
TextureFileName { "Image.png"; }
}

Mesh MyMesh
{
MeshMaterialList
{
1;
Material Material1
{
1.0; 1.0; 1.0; 1.0;;
64.0;
0.5; 0.5; 0.5;;
0.0; 0.0; 0.0;;
TextureFileName { "Image.png"; }
}
}
}


System.Reflection has answers the problem for me.

Currently all my program will do is read the data from the .x file
display it with DirectX and save it back to file but I am hoping to
add the ability to modify the 3d model or build one from scratch with
it.

Then maybe look in to saving the data in the binary format.

Thank you all for the help.

Jay Dee.
 
P

Peter Duniho

Jay said:
[...]
Then when it can to saving the data back the file I became stuck
because it was repeating the data rather than making a reference to
it.

E.g.

[...]
Mesh MyMesh
{
MeshMaterialList
{
1;
{ Material1 }
}
}

Was being output as:

[...]
Mesh MyMesh
{
MeshMaterialList
{
1;
Material Material1
{
1.0; 1.0; 1.0; 1.0;;
64.0;
0.5; 0.5; 0.5;;
0.0; 0.0; 0.0;;
TextureFileName { "Image.png"; }
}
}
}


System.Reflection has answers the problem for me.

As I suspected, your problem has absolutely zero to do with Reflection.
You may have used some feature in Reflection to address it, but
there's no need to at all. You just need to make the code more
intelligent about how it writes the data out.

Pete
 
J

Jay Dee

I wooden have a clue what I am doing wrong then. I have completed year
1 of HND computing that covered the basics of programming and the rest
I have picked up of the net.

I am eager to learn if you could point me to some good study material.
The actual project is not so important. It was just a learning
experience.

Thank you

Jay Dee.
 
J

Jay Dee

I am still slightly confused about references and values for example:

void MyVoid(ref string theString)
{
// Modify theString
}

If I modify theString then because it is a ref it will be modified
where it has come from not just in this void, but what if for example:

string theString;
void MyVoid(ref string theString)
{
this.theString = theString;
}
void MyVoid2()
{
// Modify theString
}

Is theString still a reference or has a copy bean made of the contents
of that reference.

Thanks

JayDee
 
P

Peter Duniho

Jay said:
[...]
string theString;
void MyVoid(ref string theString)
{
this.theString = theString;
}
void MyVoid2()
{
// Modify theString
}

Is theString still a reference or has a copy bean made of the contents
of that reference.

You should definitely look at Jon's article on parameter passing.

As far as the specific question goes, you didn't post enough code to
answer it, and you use the identifier "theString" two different places,
so it's hard to know which one you're asking about.

But generally speaking, what a reference refers to is never copied; only
the reference itself is. A copy is only made when you explicitly do so
(often via a method named Clone()).

Pete
 
P

Peter Duniho

Jay said:
I wooden have a clue what I am doing wrong then. I have completed year
1 of HND computing that covered the basics of programming and the rest
I have picked up of the net.

I am eager to learn if you could point me to some good study material.
The actual project is not so important. It was just a learning
experience.

Well, the basic issue here is that the output you're talking about
doesn't have to do with an object being a reference or not. It has to
do with your code knowing enough about the file format to know that an
object that contains a reference to another object can simply refer to
that object by name in the output file, rather than copying all of the
data from that object to the output file.

You shouldn't need to have to check whether the object type is a
reference, and for sure it doesn't matter whether it's been passed _by
reference_ (which is completely different...see Jon's article, please).
All you really need to know is that you're (in your example) writing a
Mesh structure, and so when you have something in that Mesh structure
that refers to something you've already written out as its own structure
in the file, you just write that as a reference to that structure,
rather than explicitly writing the whole structure.

I don't have enough knowledge off the top of my head of the DirectX file
format to be able to tell you exactly what logic to use, but you should
think more about the behavior you're trying to implement, and do what is
needed to make sure the code implements that behavior. I know that
sounds like generic, possibly useless advice, but it's really pretty
much the fundamental strategy to all programming. You can't write a
good implementation unless you have a very clear idea of what behavior
you actually want.

Also, keep in mind that the word "reference" is used in a wide variety
of different situations. Even in this one thread, we've got at least
three uses: a reference to an object instance, a reference within the
DirectX file format, and passing by reference (this last one is almost
certainly irrelevant to the question of writing a DirectX file).

It's very important to understand that just because it's the same word,
that doesn't mean it's the same concept.

Pete
 
J

J.B. Moreno

Jon Skeet said:

Speaking of which, I think the section

"Sidenote: what is the difference between passing a value object by
reference and a reference object by value?"

Could use some work. You explain it, but don't make it clear (IMO)
that the explanation is the answer to the question.

(That is to say, I think I'm criticizing your formatting, and not your
content, although changing the content might make the formatting
problem irrelevant).
 
J

Jon Skeet [C# MVP]

J.B. Moreno said:
Speaking of which, I think the section

"Sidenote: what is the difference between passing a value object by
reference and a reference object by value?"

Could use some work. You explain it, but don't make it clear (IMO)
that the explanation is the answer to the question.

(That is to say, I think I'm criticizing your formatting, and not your
content, although changing the content might make the formatting
problem irrelevant).

I'll try to have a look, although my priorities are elsewhere just at
the moment. If there's a reasonably simple fix I'll do it.
 
J

Jon Skeet [C# MVP]

J.B. Moreno said:
Speaking of which, I think the section

"Sidenote: what is the difference between passing a value object by
reference and a reference object by value?"

Could use some work. You explain it, but don't make it clear (IMO)
that the explanation is the answer to the question.

(That is to say, I think I'm criticizing your formatting, and not your
content, although changing the content might make the formatting
problem irrelevant).

Rather than changing the content (which is likely to take a long time!)
I've put the question and answer in a box. Is that any better?

I'll try to remember to take another look at this when I'm done with
the book...
 
J

J.B. Moreno

Jon Skeet said:
Rather than changing the content (which is likely to take a long time!)
I've put the question and answer in a box. Is that any better?

Yes, that's a bit better. It's now clear that the sidenote is not
simply a question which you then leave to go back to the "main"
explanation as to what a reference parameter is.
I'll try to remember to take another look at this when I'm done with
the book...

When you do so, you might want to consider making it a bit more like
the "Checking you understand the preamble" section.
 
J

Jon Skeet [C# MVP]

J.B. Moreno said:
Yes, that's a bit better. It's now clear that the sidenote is not
simply a question which you then leave to go back to the "main"
explanation as to what a reference parameter is.
Yup.


When you do so, you might want to consider making it a bit more like
the "Checking you understand the preamble" section.

Okay, will do.
 

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

Top