none
cannot modify the return value of.... because it is not a variable RRS feed

  • Question

  • I am trying to setup a structure within up to 4 different global variables on my form to be used in different functions and are fields that I don't want to be displayed on my form.  Here's what I have in my coding up top so far:

            public struct CitationItems
            {
                public string ChargeFineAmount;
                public string ChargeFeeAmount;
                public string ChargeSurchargeAmount;
                public string ChargeSTFAmount;
                public string ChargePlusAmount;
                public string ChargeMFAmount;
            };

            public static class GlobalVars
            {
                static CitationItems _Cit1;
                public static CitationItems Cit1
                {
                    get
                    { return _Cit1; }
                    set
                    { _Cit1 = value; }
                }

            }

    The problem I am having is an error in my error list for the following line of code in a calculation function:

                        GlobalVars.Cit1.ChargeFineAmount = inCash_Fine_amt;

    Description is "Cannot modify the return value of 'myprogram.Form1.GlobalVars.Cit1' because it is not a variable" 

    Unless I am misunderstanding something, I'm not sure how to properly get this to work without it giving me a red X error indicator.

    Thursday, December 20, 2012 8:08 PM

Answers

  • The error message is telling you that you have a bug in you're code.  You're only ever mutating a temporary copy that will be thrown away, and the compiler knows that, and rather than let you write some code that won't work, it's giving an error.  Be thankful that the compiler is doing you this favor.

    You're using a struct, instead of a class.  A struct is a value type.  A variable of that type actually contains the value, not just a reference to the value.  This means that when you assign one variable to another you're copying the entire value, you're not just copying the reference to an object elsewhere.

    This copying will happen when you return the value from the property.  The return value of the property is a *copy* of the structure, not a reference to it.  When you change a property of that copy, if it were allowed to compile, it would just be thrown into nothingness right after the end of that line.

    While it's certainly *possible* to make it work as a structure, in this case the problem is that you shouldn't be using a struct in the first place, you should be using a class.  As a rule you should be using a class instead of a struct unless you have a compelling reason to use a struct and you know what you're doing when you use it.

    If you change "CitationItems" from a struct to a class the error will go away and the code will work as you intended.

    Thursday, December 20, 2012 8:19 PM
  • So far things are working as desired.  I'm curious about the Static GlobalVars() part within my public static class GlobalVars part

    That's a static constructor. It is triggered by the first instantiation of the class or the first access to one of the static members of the class.

    In the case of your GlobalVars class, the static constructor executes the first time you get the value of Cit1, Cit2, Cit3 or Cit4. In other words, it is executed when you need it.

    • Proposed as answer by Jason Dot Wang Monday, December 24, 2012 6:53 AM
    • Marked as answer by Jason Dot Wang Monday, December 31, 2012 5:07 AM
    Friday, December 21, 2012 4:44 PM

All replies

  • The error message is telling you that you have a bug in you're code.  You're only ever mutating a temporary copy that will be thrown away, and the compiler knows that, and rather than let you write some code that won't work, it's giving an error.  Be thankful that the compiler is doing you this favor.

    You're using a struct, instead of a class.  A struct is a value type.  A variable of that type actually contains the value, not just a reference to the value.  This means that when you assign one variable to another you're copying the entire value, you're not just copying the reference to an object elsewhere.

    This copying will happen when you return the value from the property.  The return value of the property is a *copy* of the structure, not a reference to it.  When you change a property of that copy, if it were allowed to compile, it would just be thrown into nothingness right after the end of that line.

    While it's certainly *possible* to make it work as a structure, in this case the problem is that you shouldn't be using a struct in the first place, you should be using a class.  As a rule you should be using a class instead of a struct unless you have a compelling reason to use a struct and you know what you're doing when you use it.

    If you change "CitationItems" from a struct to a class the error will go away and the code will work as you intended.

    Thursday, December 20, 2012 8:19 PM
  • While I don't have lot of experience using custom classes, is there an example I how I can change my CitationItems struct to a class so I can populate multiple values that depend on this?  Ultimately I will be populating an XML file for output.

    as simple as changing public struct CitationItems

    to

    public class CitationItems?

    Edit: while above doesn't give me an error, when I run the code I now get a "NullReferenceException was unhandled" Object reference not set to an instance of an object" message



    • Edited by jfalberg Thursday, December 20, 2012 8:38 PM
    Thursday, December 20, 2012 8:28 PM
  • as simple as changing public struct CitationItems

    to

    public class CitationItems?

    Yes.

    Also, I see that all of the variables are suffixed with "Amount" but they're strings.  If they represent currency amounts they should probably be of type "decimal" instead of "string".

    Having public fields is also considered bad practice.  You should probably use properties instead.  The syntax is easy enough, just put in a `{get;set;}` after the variable name for each of the amounts and remove the semicolon.  

    Thursday, December 20, 2012 8:39 PM
  • Since there will be no format nor calculation changes necessary, I'm keeping as string for now.

    Hmmm I'm still getting a NullException message when I changed my struct to class with get/set as follows:

            public class CitationItems
            {
                static string _s;
                public string ChargeFineAmount { get { return _s; } set {_s = value; } }
                public string ChargeFeeAmount { get { return _s; } set { _s = value; } }
                public string ChargeSurchargeAmount { get { return _s; } set { _s = value; } }
                public string ChargeSTFAmount { get { return _s; } set { _s = value; } }
                public string ChargePlusAmount { get { return _s; } set { _s = value; } }
                public string ChargeMFAmount { get { return _s; } set { _s = value; } }
            };


    • Edited by jfalberg Thursday, December 20, 2012 8:54 PM
    Thursday, December 20, 2012 8:53 PM
  • public class CitationItems
    {
         public string ChargeFineAmount { get; set; }
         public string ChargeFeeAmount { get; set;}
         public string ChargeSurchargeAmount { get; set;}
         public string ChargeSTFAmount { get; set; }
         public string ChargePlusAmount { get; set; }
         public string ChargeMFAmount { get; set; }
    };
    
    then to use it
            CitationItems items = new CitationItems;
         items.ChargeFineAmount = "1000";
         items.ChargeMFAmount = "2000";
     

    "jfalberg" wrote in message news:68621110-bfe8-4c55-873f-c5181fa0e657@communitybridge.codeplex.com...

    Since there will be no format nor calculation changes necessary, I'm keeping as string for now.

    Hmmm I'm still getting a NullException message when I changed my struct to class with get/set as follows:
            public class CitationItems
           {
               static string _s;
               public string ChargeFineAmount { get { return _s; } set {_s = value; } }
               public string ChargeFeeAmount { get { return _s; } set { _s = value; } }
               public string ChargeSurchargeAmount { get { return _s; } set { _s = value; } }
               public string ChargeSTFAmount { get { return _s; } set { _s = value; } }
               public string ChargePlusAmount { get { return _s; } set { _s = value; } }
               public string ChargeMFAmount { get { return _s; } set { _s = value; } }
           };

    Thursday, December 20, 2012 9:22 PM
  • Getting back to my global field that I intend to use for various functions, populating, writing to an external file, both separate functions:

            public static class GlobalVars
             {
                 static CitationItems _Cit1;
                 public static CitationItems Cit1
                 {
                     get
                     { return _Cit1; }
                     set
                     { _Cit1 = value; }
                 }
             }

    Intellisense doesn't seem to like

    CitationItems GlobalVars.Cit1 = new CitationItems;

    I would like to use this globally so I don't have to keep transferring values from one function to another where it's needed.

    I need to make it publicly available.  Is there another way to do this? 

    Thursday, December 20, 2012 9:39 PM
  • In `GlobalVars` it doesn't make sense to allow the item to be set, just gotten; it should effectively only ever exist once:

    public class CitationItems
    {
        public string ChargeFineAmount { get; set; }
        public string ChargeFeeAmount { get; set; }
        public string ChargeSurchargeAmount { get; set; }
        public string ChargeSTFAmount { get; set; }
        public string ChargePlusAmount { get; set; }
        public string ChargeMFAmount { get; set; }
    }
    
    public static class GlobalVars
    {
        static GlobalVars()
        {
            Cit1 = new CitationItems();
            //TODO: initialize each string to some default value that makes sense
        }
        public static CitationItems Cit1 { get; private set; }
    }

    Another option would be to get rid of "GlobalVars" entirely (or just not use it for this):

    public static class CitationItems
    {
        static CitationItems()
        { 
            //TODO: set initial values here, if they shouldn't be null.
        }
        public static string ChargeFineAmount { get; set; }
        public static string ChargeFeeAmount { get; set; }
        public static string ChargeSurchargeAmount { get; set; }
        public static string ChargeSTFAmount { get; set; }
        public static string ChargePlusAmount { get; set; }
        public static string ChargeMFAmount { get; set; }
    }

    Thursday, December 20, 2012 10:13 PM
  • So far things are working as desired.  I'm curious about the Static GlobalVars() part within my public static class GlobalVars part

                static GlobalVars()
                {
                    Cit1 = new CitationItems();
                    Cit2 = new CitationItems();
                    Cit3 = new CitationItems();
                    Cit4 = new CitationItems();
                }
                public static CitationItems Cit1 { get; private set; }
                public static CitationItems Cit2 { get; private set; }
                public static CitationItems Cit3 { get; private set; }
                public static CitationItems Cit4 { get; private set; }

    • Proposed as answer by Louis.fr Friday, December 21, 2012 4:40 PM
    • Unproposed as answer by Louis.fr Friday, December 21, 2012 4:44 PM
    Friday, December 21, 2012 3:48 PM
  • So far things are working as desired.  I'm curious about the Static GlobalVars() part within my public static class GlobalVars part

    That's a static constructor. It is triggered by the first instantiation of the class or the first access to one of the static members of the class.

    In the case of your GlobalVars class, the static constructor executes the first time you get the value of Cit1, Cit2, Cit3 or Cit4. In other words, it is executed when you need it.

    • Proposed as answer by Jason Dot Wang Monday, December 24, 2012 6:53 AM
    • Marked as answer by Jason Dot Wang Monday, December 31, 2012 5:07 AM
    Friday, December 21, 2012 4:44 PM