static list not behaving as expected

Hello,
I am new to c#. I am developing a wcf service. I have a global class under which all of my classes are defined

           
   public static globals MyGlob = new globals();


    public class globals
    {
        public static UserMaster MyUser;
        public static TransactionHdr MyTransHdr;
        public static TransactionSeq MyTransSeq;
        public static ErrorMsgs MyErrMsgs;

        public static List<TransactionHdr> MyTransHdrList;
        public static List<TransactionSeq> MyTransSeqList;
        public static List<ErrorMsgs> MyErrMsgsList;
       
        public static Dictionary<string, int> MyTagsDict;
        public static Dictionary<string, string> MyVarValuesDict;
        public static Dictionary<string, string> MyKeywordsDict;
                       
I create the MyErrMsgsList as follows:
MyErrMsgsList = new List<ErrorMsgs>();

         
When I come to populate the full list of available error messages to the error messages List (lets say this transaction  has 20 error messages available) - all 20 error messages are identical to the last error error message populated to the list.

case "error_messages": // Error Messages
// Transaction error messages are extract into myStrArray and these and e9% messages are then read
                                        globals.MyErrMsgs.companyId = row.ItemArray[0].ToString().Trim().ToLower();            //Err Msg CompanyId
                                        globals.MyErrMsgs.errMsgId = row.ItemArray[1].ToString().Trim().ToLower();                //Err Message Id
                                        globals.MyErrMsgs.description1 = row.ItemArray[2].ToString().Trim();                            // Description 1
                                        globals.MyErrMsgs.description2 = row.ItemArray[3].ToString().Trim();                            // Description 2
                                        globals.MyErrMsgsList.Add(globals.MyErrMsgs);

My Dictionaries are being populated correctly but not my lists. Appreciate if some can point out what I am doing wrong.

regards
Pat
LVL 1
pclarke7Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

QlemoBatchelor, Developer and EE Topic AdvisorCommented:
You need to create a new ErrorMsgs instance for each error message, otherwise you are modifying the same object. just adding the same reference (pointer) to the list each time. The referenced object of course contains the last value only then.
0
Jacques Bourgeois (James Burger)PresidentCommented:
When you Add a variable based on a class to a list, you are not making a copy as is the case with simple variables. You simply add its address in memory to the list. By default, if you Add the same variable 20 times, you are simply having a list of 20 pointers that point to the same block of memory.

When you make a change to globals.MyErrMsgs, you are changing that single block of memory (called an instance in object terminology) and it reflects in the 20 entries in your list, because they all point to the same block of memory.

As stated by Qlemo, you thus need to create a new object for each of your error message:

ErrorMsgs MyErrMsgs;

MyErrMsgs = new ErrorMsgs();
case "error_messages": // Error Messages
MyErrMsgs.companyId = row.ItemArray[0].ToString().Trim().ToLower();
MyErrMsgs.errMsgId = row.ItemArray[1].ToString().Trim().ToLower();
MyErrMsgs.description1 = row.ItemArray[2].ToString().Trim();
MyErrMsgs.description2 = row.ItemArray[3].ToString().Trim();
MyErrMsgsList.Add(globals.MyErrMsgs);
MyErrMsgsList.Add(MyErrMsgs);

MyErrMsg should not be defined either as static or into the globals. MyErrMsgsList plays that role.

Notice that I have moved MyErrMsgs out of the globals. Simply define it in the method where you use it, being sure to instantiate it to a new object (call new on the variable) for each new message.

Each "new" creates a completely new object, pointing to a new block of memory, independant from the previous one. But if you've added that previous one to the list, the framework will keep it alive as long as the list itself lives. You've just used one variable to create 20 objects in memory.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AndyAinscowFreelance programmer / ConsultantCommented:
Some similar info to the previous two comments:

Nothing is wrong with your list - that is working correctly.

There are two distinct sorts of variables, reference types and value types.  Reference types are eg. classes which are reused.  Value types are simple variables (eg. int, bool, string) and structures, these are not reused.  Assigning a different value to a class means the original variable is modified - even if you have added it to some collection elsewhere.
You need to understand this behaviour not just to solve this problem but to help you in making code that functions as you want in future.
0
pclarke7Author Commented:
Thank you all for your contributions.  Code now modified and working as expected. It is a good lesson to lean also. I assume that dictionaries are value type rather than reference type which would account for why they were populating correctly.
0
Jacques Bourgeois (James Burger)PresidentCommented:
It's not the list or the dictionary, they are both reference types.

It's what you put in them. You fill your dictionaries with basic types such as int, which are value types. You fill your list with MyErrMsgs, wich is a class by the behavior you were describing.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.