none
Build up a variable name with a string RRS feed

  • Pergunta

  • Hi,

    I wonder if there's a way (in c#) to build up a variable name
    by the concatenation of two strings...For example

    int intTest = 1;

    string strTest = "strTest";

    string strTest+intTest.toString() = "this is my new var";

    Thanks in advance

    segunda-feira, 9 de outubro de 2006 11:34

Respostas

  • I don't think you can make a variable name based on what you enter in a string. I could be wrong but never seen this done before and when you try to do it like you have done, compiler will of course complain.

     

    segunda-feira, 9 de outubro de 2006 11:41
    Moderador
  • You can't do this because C# is a compiled language. Dynamic operations like that can be handled in interpreted languages, such as Javascript (which can do it using the eval method).

    Can you use an array or some kind of collection to achieve the result you want?

    segunda-feira, 9 de outubro de 2006 14:12

Todas as Respostas

  • I don't think you can make a variable name based on what you enter in a string. I could be wrong but never seen this done before and when you try to do it like you have done, compiler will of course complain.

     

    segunda-feira, 9 de outubro de 2006 11:41
    Moderador
  • You can't do this because C# is a compiled language. Dynamic operations like that can be handled in interpreted languages, such as Javascript (which can do it using the eval method).

    Can you use an array or some kind of collection to achieve the result you want?

    segunda-feira, 9 de outubro de 2006 14:12
  •  Mark Rendle wrote:

    operations like that can be handled in interpreted languages, such as Javascript (which can do it using the eval method).

    Or in VFP: via macro substitutions-a very nice feature.

    segunda-feira, 9 de outubro de 2006 14:42
  • Its not possible but there must be many alternates. Would you like to explain your scenerio where you need this?

    Best Regards,

    segunda-feira, 9 de outubro de 2006 14:59
  • >> Or in VFP: via macro substitutions-a very nice feature.

    Well.. that's debatable.   I saw them a lot years ago when I was coding in Clipper (which, like FoxPro originally, was a dBase III compiler).  I've never seen a good design that used them, but I've seen a lot of bad designs that did.  They seem to lead to the "quick shortcut" mentality (*) that just makes mess out of code.  Further, it forces the compiler to shutdown and revert back to being an interpreter (which means that your EXE must include the full interpreter with it)

    (*)  An example:  I would often see code like this:


    MyVar = "World"
    MyVar2 = "Hello &MyVar"

     

    as opposed to the equivalent (and fully compilable) version:


    MyVar = "World"
    MyVar2 = "Hello " + MyVar

     

    segunda-feira, 9 de outubro de 2006 15:57
  • Well, if the "world" is a variable as opposed to MyVar which is a string then it makes perfect sense. After you applied &MyVar like this:

    &MyVar  = "Hello "

    you should get:

    world == "Hello "

    the world becomes a string with content: "Hello "

    It makes a lot of sense when the names of variables are not known in advance of too tedious to define all of them. Let's say you have a grid with 150 columns and you want to address them all by name "Column1" "Column2" etc. The macro substitutions are very handy for doing it. You define a macro in a loop: colName = "Column"+ALLTRIM(STR(ii)) where ii is the loop counter and you have your column name ready: &colName.

    There are many other situations where the macros of VFP save a lot of code space. I suspect they may be equivalent to some inline functions in C# but I am not entirely sure: I am green in C# myself.

    segunda-feira, 9 de outubro de 2006 16:54
  • >> Let's say you have a grid with 150 columns and you want to address them all by name "Column1" "Column2" etc. The macro substitutions are very handy for doing it. You define a macro in a loop: colName = "Column"+ALLTRIM(STR(ii)) where ii is the loop counter <<

    Modern programming languages have a thing called an Array.  Perhaps you should look into it......

    (I've not idea how VFP handles it, but when I was working in Clipper -- late 1980s! --- creating a variable like, without previously declaring it, made a mess out of memory management, which in those days of 640K DOS, was deadly)

    segunda-feira, 9 de outubro de 2006 17:03
  •  James Curran wrote:

    Modern programming languages have a thing called an Array.  Perhaps you should look into it......

    What does Array have to do with the subject?

    segunda-feira, 9 de outubro de 2006 17:44
  • It occured to me to take a look at the way my grid with 16 columns is defined in the constructor as well as how my table with equal number of columns or a tabControl with 24 tabpages are defined. With macro substitutions I could have compressed a few hundred statements down to perhaps a dozen. They all have some regularity in them. Those laws are easily noticeable. You set up a few macros in a loop and just add a few characters as loop rolls. That's it. These dozen or so macros are used only once during the compilation and at runtime the OS deals with its few hundred statements.
    segunda-feira, 9 de outubro de 2006 17:54
  • Have you heard of a Hashtable or Dictionary<>? Use it to store key(variable name) and value (value of variable) pairs. This would be better I think. C# can't do what you want except for maybe with reflection or emit.
    segunda-feira, 9 de outubro de 2006 18:34
  •  KyleB wrote:
    Have you heard of a Hashtable or Dictionary<>? Use it to store key(variable name) and value (value of variable) pairs. This would be better I think. C# can't do what you want except for maybe with reflection or emit.

    How can you use a HashTable in a constructor? You can use it at runtime but not to build a series of objects with some common features.

    segunda-feira, 9 de outubro de 2006 19:45
  • What does Array have to do with the subject?

    How exactly is



    colName = "Column"+ALLTRIM(STR(ii))
    &colName = somevalue

     

    significantly different from



    Column(II) = somevalue

     

    ??? (where Column()  is an Array)

    segunda-feira, 9 de outubro de 2006 19:52
  • If you're doing the same thing to 16 columns, you just create a function which does it and call it sixteen times. If your grid exposes a collection of columns, you foreach through it calling the function. Yes, there are occasions where macros might enable a shortcut or two, but not enough (IMO) to outweigh the negative aspects like confuddled compiler messages and nightmarish debugging issues. After all, we apparently spend more time debugging than coding...
    terça-feira, 10 de outubro de 2006 09:33
  •  James Curran wrote:

    What does Array have to do with the subject?

    ??? (where Column()  is an Array)

    I am really sorry for a misstatement. The macros are not used in the constructor in VFP but you can use them to significantly simplify the constructor as I will show on C# example. I want you, James, to figure out how I can do it with Arrays in here. It will be very helpful for me.

    I glued up 24 statements from my InitializeComponent () Form1 function.

    this.tp_A = new System.Windows.Forms.TabPage ( );
    this.tp_C = new System.Windows.Forms.TabPage ( );
    ..........................
    this.tp_Y = new System.Windows.Forms.TabPage ( );
    this.tp_Z = new System.Windows.Forms.TabPage ( );

    There are as I said 24 tabs in that tabPage2 with a letter on each tab to select a subset of individuals from a customer file. You click on "C" and people with names starting with a C will be shown in a listBox, James Curran including:)

    If I had a VFP way to do things in here I would remove all 24 lines from this procedure and a number of others and stored these lines in Form1.Load method:

    for ( int alpha = 65; alpha <= 90; alpha++ )
        {
            string macro1 = "this.tp_" + alpha.ToString ( ).Trim ( ) + " = new System.Windows.Forms.TabPage ( );";
            &macro1; // OF COURSE THIS IS NOT ALLOWED. IT IS A FANTASY C#
         }

    Instead of 24 statements I would have just 3.

    OK?

    Thanks

    terça-feira, 10 de outubro de 2006 17:14
  • There are shorter ways I could have coded this, but this gives the most flexibility(*).



    using System.Windows.Forms;
    string tablabels = "ACDEFGHIKLMNOPQRSTUVWXYZ";
    TabPage[]  tp = new TabPage[tablabels.Length];
    int i = 0;
    foreachchar alpha in tablabels )
    {
             tp[ i ] = new TabPage();
             tp[ i ].Text = alpha;      // you seemed to have skipped that step.
             ++i;
     }

     

    So, I repeat the question.  How is your way, with macros any better/different than my way with an array?


    (*)  To clarify the "most flexibility" claim, in your example, you said your C# code had 24 tabs, and shows an A & a C, but no B.  Your macro code would have 26 tabs, including a "B".   Mine has only 24 tabs skipping B (and J).   If you wanted just 5 tabs (A, E, I, O U) all you need do is change teh tablabels line.

    terça-feira, 10 de outubro de 2006 19:07
  • "tp[ i ].Text = alpha;      // you seemed to have skipped that step."

    I haven't. It is taken care of but in a C# way. I just gave you an illustration.

    Well, it seems to be possible to do it your way. I just have to get used to it. I still believe that there are many cases when macros can offer an advantage. I will have to scout my VFP code to see it. I've got many.

    It is interesting--what you've shown.

    Thank you.

    terça-feira, 10 de outubro de 2006 19:45
  • >> I haven't. It is taken care of but in a C# way. I just gave you an illustration.

    I kinda figured as much, but I wasn't using the variable "alpha" without that line.


    But, we now need to move to the larger point ---- Answering your unasked question "Ok, James, You've shown that macros may be unnecessary, but why do you say they are bad?"

    Let's consider another version of that code, this time a little closer to your macro version:



    Dictionary<char, TabPage> tp = new Dictionary<char, TabPage>();
    for ( char alpha = 'A'; alpha <= 'Z'; alpha++ )
    {
            this.tp[alpha]= new System.Windows.Forms.TabPage ( );
    }

     

    Now I can do anything with tp['A'] that I could have do with tp_A in you example.  Taking that a step further, I could define it like this:



    Dictionary<string, Object> syms = new Dictionary<string, Object>();
    for ( char alpha = 'A'; alpha <= 'Z'; alpha++ )
    {
            syms["tp_" + alpha]= new System.Windows.Forms.TabPage ( );
    }

     

    This would give me many of the abilities you have with macros.  For example where you would write:

    varname = "tp_" + tab
    &varname.Text = "James";

    I could write

    varname = "tp_" + tab;
    syms[varname].Text = "James";

    except that last line wouldn't compile in C#, because syms[] returns an Object, which doesn't have a Text property. So, to allow that to compile, I'd have to shut down all compile-time checking of properties, and then at run-time using reflection to determine if the object returned by syms[varname] is of a type that has a Text property. 

    Further, let's say you'd written the original code like this:


    string incr = "alpha";
    for ( int alpha = 65; alpha <= 90; &incr++ )
        {
            string macro1 = "this.tp_" + alpha.ToString ( ).Trim ( ) + " = new System.Windows.Forms.TabPage ( );";
            &macro1; 
         }

     

    Now, the equivalent of that becomes:



    Dictionary<string, Object> syms = new Dictionary<string, Object>();
    string incr = "alpha";
    for ( syms["alpha"] = 'A'; (char)(syms["alpha"]) <= 'Z'; syms[incr] = (char)(syms[incr])++ )
    {
            syms["tp_" + syms["alpha"]  ]= new System.Windows.Forms.TabPage ( );
    }

     

    In fact, since I'd never know when you'll refer to a variable by it's literal name ("alpha") or through a macro ("&incr") -- but both reference must refer to the same variable -- I would be forced use the syms dictionary for every single variable in my program.  This would make accessing any bit of data much slower, and move much which is now done at compile-time to runtime.

    The point here, is that because FoxPro supports macros, it's required to do all of this because you might use a macro.  It does a good job of hiding the gory details from our view, but it's still doing them behind the scenes, and it's still taking up time & system resources.

     

     

     

     

     

     

     

    terça-feira, 10 de outubro de 2006 20:29
  • "I kinda figured as much, but I wasn't using the variable "alpha" without that line."

    Well, you've thrown a stack of information on me. I hope to digest it tomorrow. In the meantime I do have a question. How do you handle a situation like this. If I were doing it in FFP I would have used macros. It is a practical issue for me right now in C#.

    I need to compose an sql statement for OleDbConnection. In this particular example it would be a delete statement. I can either have a loop doing it piecemeal or include them in one statement wholesale. I prefer the second approach.

    The field values for a primary key field are stored in an array. I do not know in advance how large the array would be: it is up to the customer to decide how many records should be deleted. The statement looks like this:

    xxxxxx.commandText = "DELETE FROM users WHERE univRec_id = \"" + intArrOfDelRows[0].ToString ( ).Trim ( ) + " \"";

    At this point I am just testing the connection and if it would delete just one row. Would it work if I put in the whole array name without the [Index] part? How can I force this sql delete a bunch of them, the whole intArrOfDelRows of them in just one step?

    Will much appreciate your insight.

    Thanks.

     

    quarta-feira, 11 de outubro de 2006 20:20

  • int[] intArrOfDelRows = {1,2,3,4,5,6};

    string commandText = "DELETE FROM users WHERE univRec_id in (" +
    String.Join("
    , ", Array.ConvertAll<int, string>(intArrOfDelRows, delegate(int i){ return i.ToString();})) +
    "
    )";

     

    DELETE FROM users WHERE univRec_id in (1, 2, 3, 4, 5, 6)

    Reading that from the inside out: Take an array of ints and convert it to an array of strings, then join those strings into one big string (with a comma-space between each).

    quarta-feira, 11 de outubro de 2006 20:46
  • James, I greatly apreciate your code as well as the lesson you gave me and countless others, I hope, in the previous post on the "badness" of macros.

    Thanks you.

    quinta-feira, 12 de outubro de 2006 14:23
  • Try using pointers
    sábado, 7 de maio de 2011 13:53
  • use the Convert.ToInt(strText) method
    • Editado DerrickKoehn segunda-feira, 29 de junho de 2020 01:31
    segunda-feira, 29 de junho de 2020 01:30