get name of variable as string?

  • Thread starter Thread starter Zytan
  • Start date Start date
Well, this is one of the few cases where macros could actually be useful.

Yes,
Generally they are not needed at all, so they would mostly be misused if
available. I believe that not including macros in C# was a good design
decision after all.

I understand and agree.

But, it destroys all the great debugging tools we can make with them,
and since debugging is often a useful thing to do, these features
should have been supplemented with something. Everyone debugs, after
all. And the debugger is powerful, so they do 'get it', it's just
that sometimes, it'd be nice to not have to fire up the chainsaw when
a butter knife will do.

I feel l am being scolded with the rest of the class, just beacuse I
was there, even though I wasn't one of the bad kids misbehaving. The
teacher should at least give me a candy.

Zytan
 
Zytan said:
I meant that it returns a string that is equivalent to what you type
in code. I didn't mean to imply it returns the hidden integer that
exists inside (that you don't have access to unless you explicitly
type cast it). Thus, the value returned is exactly the 'value' you
must type in code (not the hidden value that, for the most part, you
shouldn't ever see or use). This is precisely what I want for a
variable of type int. I want "i" from a variable "int i;", just as I
get "Google" from "MyEnum.Google"

Variable name and variable value are different things.

int and enum behave the same.

int i = 1;
Colour c = Colour.Green;
Console.WriteLine(i);
Console.WriteLine(c);

writes the value of i and c ("1" and "Green") not the names "i" and "c".

Arne
 
Variable name and variable value are different things.
int and enum behave the same.

int i = 1;
Colour c = Colour.Green;
Console.WriteLine(i);
Console.WriteLine(c);

writes the value of i and c ("1" and "Green") not the names "i" and "c".

Yes. I was just trying to explain what I wanted, and it was a very
bad example to use enums, because people were thinking about the
integer that represents the enum, when the actual value (from C#'s
perspective) is 'Color.Green', not something like '45'. And then I
got a little confused trying to explain it.

To make it clear what I wanted, I'll continue your above case with the
following code. This is what I want to type:

WriteValue(i);
WriteValue(c);

And this is the result I want:

i = 1
c = Color.Green

Which is much easier for debugging than the laborious:

WriteLine("i = " + i);
WriteLine("c = " + c);

Zytan
 
I feel l am being scolded with the rest of the class, just beacuse I
was there, even though I wasn't one of the bad kids misbehaving. The
teacher should at least give me a candy.

So how would you have designed the language to allow macro support
"only in the cases where it's appropriate"?

There is *so* much code abusing macros out there, it's clearly too much
of a temptation for most developers.
 
Zytan said:
Yes. I was just trying to explain what I wanted, and it was a very
bad example to use enums, because people were thinking about the
integer that represents the enum, when the actual value (from C#'s
perspective) is 'Color.Green', not something like '45'. And then I
got a little confused trying to explain it.

To make it clear what I wanted, I'll continue your above case with the
following code. This is what I want to type:

WriteValue(i);
WriteValue(c);

And this is the result I want:

i = 1
c = Color.Green

Which is much easier for debugging than the laborious:

WriteLine("i = " + i);
WriteLine("c = " + c);

You want the equivalent of:

#define PRINT(z) cout << #z << " = " << (z) << endl;

:-)

But that is not possible in C#. It is only possible in C++ due
to the preprocessor.

Arne
 
You want the equivalent of:
#define PRINT(z) cout << #z << " = " << (z) << endl;

:-)

But that is not possible in C#. It is only possible in C++ due
to the preprocessor.

Precisely! :) But, C# doesn't allow it since macros can mangle code,
which is true. But, I just want them for simple debugging tools like
this. So, i'd be just as happy if C# provided the debugging tools
themselves, instead of the macros. I know the debugger itself is
great, but sometimes you just want something quick, and sometimes many
of these PRINT statements really can help.

Zytan
 
I feel l am being scolded with the rest of the class, just beacuse I
So how would you have designed the language to allow macro support
"only in the cases where it's appropriate"?

Sorry, I meant to imply that C# was correct to not include macros, but
that they could supplement that loss by adding something ELSE that at
least lets us do what we could with proper macro writing. Say, by
giving us __FILE__, __FUNCTION__, and maybe even my cherished
PRINTVALUE macro that automatically shows the function name, the
variable name, the = sign, and the value, so I can quickly see in the
log / console where and what that value is. Maybe I'm along in
wanting something like this. Seems not many people make use of a
logger / console to debug.

Oh, and even if I can not solve this problem, it doesn't mean it
cannot be solved, say, by someone who has had a decade of experience
designing languages.
There is *so* much code abusing macros out there, it's clearly too much
of a temptation for most developers.

I agree.

Zytan
 
Zytan said:
Sorry, I meant to imply that C# was correct to not include macros, but
that they could supplement that loss by adding something ELSE that at
least lets us do what we could with proper macro writing. Say, by
giving us __FILE__, __FUNCTION__, and maybe even my cherished
PRINTVALUE macro that automatically shows the function name, the
variable name, the = sign, and the value, so I can quickly see in the
log / console where and what that value is. Maybe I'm along in
wanting something like this. Seems not many people make use of a
logger / console to debug.

I do - but I've never particularly had the need to use something like
PRINTVALUE. I keep track of which line I'm printing stuff out from,
then I can see which value is meant to be what from that. Or I just do:

Console.WriteLine ("i={0} j={1}", i, j);

I don't spend so much time debugging that doing the above is a
significant effort. I usually feel that if I've got to that stage, my
code probably isn't clear enough to start with, or I haven't got enough
unit tests. (It's not always the case, of course, but it's a good
initial rule of thumnb.)
Oh, and even if I can not solve this problem, it doesn't mean it
cannot be solved, say, by someone who has had a decade of experience
designing languages.

That's true, of course.
 
Zytan said:
WriteValue(i);
WriteValue(c);

And this is the result I want:

i = 1
c = Color.Green

Which is much easier for debugging than the laborious:

WriteLine("i = " + i);
WriteLine("c = " + c);

I can't see the benefit. What's wrong with the Debug.WriteLine(i, "i") or
Debug.WriteLine(c, "c") statement? With IntelliSense you don't have to write
that much and you have many more options supporting you for debugging.

Lothar
 
You can get what you want through reflection. Below is the code that
will return you the name of your variable:

class ty
{
public int i = 0;
}
class Program
{
static void Main(string[] args)
{
ty ob = new ty();
Type t = ob.GetType();
MemberInfo[] mi= t.GetMembers();
foreach (MemberInfo m in mi)
{

Console.WriteLine(m.Name);
}
}
}

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
You can get what you want through reflection. Below is the code that
will return you the name of your variable:

Thanks JV, but the problem is that this code works only inline. It
cannot be moved into a function that could be called more easily than
actually typing the variable name manually.

In other words, I want:

int i = 123;
WriteValue(i);

to print the string:

"i = 123"

The easiest way in C# is to do this:

WriteLine("i = "+i);

Even with reflection, there's no way that's easier than the above.
Unfortunately, the only reason I want it would be because it would be
easier than typing "i" (or some other, likely longer, variable name)
twice.

Thanks for your code,

Zytan
 
Yes, you can. Override the ToString method of the object class like
below:

class ty
{
public int i = 123;
public string ToString()
{
return "i=" + i.ToString();
}
}

static void Main()
{
ty ob=new ty();
Console.WriteLine(ob.ToString());
}

will output "i=123"

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
Ravichandran J.V. said:
Yes, you can. Override the ToString method of the object class like
below:

class ty
{
public int i = 123;
public string ToString()
{
return "i=" + i.ToString();
}
}

static void Main()
{
ty ob=new ty();
Console.WriteLine(ob.ToString());
}

will output "i=123"

But again, that's not what Zytan wants - he wants to be able to get
"ob=[whatever]" because he's using the "ob" variable in Main.

You just can't do what Zytan wants to be able to do in .NET.
 
Hm...sorry abt the names of the class, Jon, but below is the first post
of zytan for your reference:

<snip>Is it possible? int.ToString()
returns the value of the int as a string, not the name, so I am thinking
'no'.
</snip>

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
I guess i have supplied two answers that you do not require (as Jon
pointed out), let me try this one.

Er...can you not use the Immediate window and type "i?" in it? I

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
Hm...sorry abt the names of the class, Jon, but below is the first post
of zytan for your reference:

<snip>Is it possible? int.ToString()
returns the value of the int as a string, not the name, so I am thinking
'no'.
</snip>

Yes, but he doesn't want to have to use a new class everywhere instead
of the real class - that would be more work than just including the
name of the variable in the log line.

Look at the code he wants to write:

<quote>
In other words, I want:

int i = 123;
WriteValue(i);

to print the string:

"i = 123"
</quote>

Note that he wants a variable called "i" which is an *int* - because,
presumably, he wants to use it elsewhere *as* an int. Creating a whole
new object every time you declare a variable, just to store the
variable name, would be crazy.

Everyone else has already concluded that what Zytan wants just isn't
feasible. Yes, we know you can override ToString in your own classes,
but that doesn't solve the problem. That allows you to name *objects*
(if you start including a name variable everywhere), but as soon as
you've got multiple variables referring to the same object, ToString()
won't be able to give you which variable you happen to have used to
called the method.

Jon
 
(This isn't technically a C# solution, but hopefully it will solve
your problem Zytan.) So you just want this capability to help you
debug values? You might have more luck solving this problem by writing
an extension for your IDE.

Assuming you use Visual Studio, there are two quick solutions....

1. If you use Resharper it comes with a live template ("outv") that
does this for you.

2. You can create a code snippet that does this for you. I've created
an example code snippet that should work for you.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/
CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Zytan's Snippet</Title>
<Shortcut>zytan</Shortcut>
<Description>Code snippet to write a variable to Console.Out</
Description>
<Author>Jay Mitchell</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>EXPR</ID>
<Default></Default>
<ToolTip>Variable</ToolTip>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[System.Console.Out.WriteLine("$EXPR
$ = {0}", $selected$ $EXPR$);
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
 
I guess i have supplied two answers that you do not require (as Jon
pointed out), let me try this one.

Er...can you not use the Immediate window and type "i?" in it?

Yes, I guess I could. But, I desired such a function for run-time
display.

Zytan
 
Here you are, Zytan. A complicated and long piece of code for obtaining
a simple value however, it fulfills your requirement. It will print
"i=123" or any variable that you may declare within a class.

I have used an inline class that is compiled on the fly. You may use an
assembly for which i have also included the ReferencedAssemblies() call
for your reference.

You will need to compile the below code with
"csc /r:base.dll source.cs"

The base.dll can be a simple class with a constructor.

You may also want to create a small assembly and replace the hard-coded
path (c:\c#_prgs\base.dll) in the code when you compile the below
program:

using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Windows.Forms;
using System;
using System.Reflection;
public class t
{
static void Main(){
Base myobj;
CSharpCodeProvider csp= new CSharpCodeProvider();
ICodeCompiler ic = csp.CreateCompiler();
CompilerParameters cparam= new CompilerParameters();
cparam.GenerateInMemory = true;
cparam.GenerateExecutable = false;
cparam.ReferencedAssemblies.Add("system.dll");
cparam.ReferencedAssemblies.Add(@"c:\c#_prgs\base.dll");
string str = "using System;"+
"class myclass:Base" +
"{"+
"public myclass(){i=123;}"+
"public int i;"+
"public string ToString()"+
"{"+
"return i.ToString();"+
"}" +
"}";
CompilerResults cres= ic.CompileAssemblyFromSource(cparam,str);
foreach (CompilerError ce in cres.Errors)
MessageBox.Show(ce.ErrorText);

if (cres.Errors.Count == 0 && cres.CompiledAssembly != null)
{
Type ObjType = cres.CompiledAssembly.GetType("myclass");
try
{
if (ObjType != null)
{
myobj = (Base)Activator.CreateInstance(ObjType);
Console.WriteLine(myobj.ToString());
FieldInfo[] f= ObjType.GetFields();
foreach(FieldInfo ff in f)
{
MessageBox.Show(ff.Name + "=" +

ff.GetValue(myobj).ToString());
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
Here you are, Zytan. A complicated and long piece of code for obtaining
a simple value however, it fulfills your requirement. It will print
"i=123" or any variable that you may declare within a class.

Can you show how it would be *used* though, bearing in mind Zytan's
preferred use case, e.g.:

int i = 45; // Must be int, not some other class, otherwise it's too
intrusive
SomeMethod (i); // Should print out "i=45"

I don't believe that your code will help him to do this - I don't
believe it's *possible* to help him to do this.

Jon
 

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