简体   繁体   中英

How to change an attribute of a public variable from outside the class

Sorry about the title, I don't think I could explain it right:

This is a simplified example class, this is working ok. (I also have a Save() method)

   public class busItem
    {

        public Item vItem;

        public busItem(int pItem_Id)
        {
            DBDataContext db = new DBDataContext();

            Item vItemQuery = (from i in db.Items
                               where i.Id == pItem_Id
                               select i).FirstOrDefault();

            vItem = new Item();

            vItem.Id = vItemQuery.Id;
            vItem.Desc = vItemQuery.Desc;

        }
    }

And this is my code-behind call:

busItem item = new busItem(1);
item.vItem.Desc = "new description";

the problem is that when I try passing the "new description", i get a "null reference" exception. How can I do that?

You're probably getting the null reference exception in the constructor. FirstOrDefault() can return null if there are no items in the IEnumerable , in which case accessing Id and Desc will cause an exception. If the constructor completes normally, item.vItem.Desc shouldn't fail.

First of all, that code doesn't look right for at least 2 reasons. pItem in the query is not declared; did you mean pItem_Id? Also, the line with "new description" doesn't end with a semicolon. Unless I'm looking at the exact code you have, there's a good chance the actual problem win't be visible. Secondly, I suspect the error is not actually when you assign "new description" but when you assign vItem.Desc = vItemQuery.Desc. I don't see how the "new description" line could be a problem, but if the query returned null because it couldn't find the requested object, you'd get an error when trying to get the original/default description.

Edit: Are you sure you didn't exclude some significant piece of code like declaring a local instance of vItem within the constructor?

I took the code Vitor posted and added two small mock implementations for DataContext and Item so I have running code. Then I added the code that fails in a test. The test passed no matter what I do with the Item object I add to the collection returned by the DataContext.

The only exception I was able to reproduce occurred in the constructor. The line where the new description is set never failed.

I have added my code below.

On a more general note: Public member variables are generally a sign that the design can be improved. I'd suggest to make this variable private and work from there. In our team we have a rule that member variables cannot be public as they lead to weak designs. Just my two cents.

  public class Item {
     public int Id;
     public string Desc;
  }

  public class DBDataContext {
     public System.Collections.Generic.List<Item> Items {
        get {
           var items = new System.Collections.Generic.List<Item> {
              new Item {
                 Desc = null,
                 Id = 1
              }
           };
           return items;
        }
     }
  }

  public class busItem {

     public Item vItem;

     public busItem(int pItem_Id) {
        DBDataContext db = new DBDataContext();

        Item vItemQuery = (from i in db.Items
                           where i.Id == pItem_Id
                           select i).FirstOrDefault();

        vItem = new Item();

        vItem.Id = vItemQuery.Id;
        vItem.Desc = vItemQuery.Desc;
     }
  }

  [Test]
  public void TestBusItem() {
     busItem item = new busItem(1);
     item.vItem.Desc = "new description";
  }

The problem is probably this code:

   Item vItemQuery = (from i in db.Items
                           where i.Id == pItem_Id
                           select i).FirstOrDefault();

FirstOrDefault will return the first item, or the default. As Item is a class, the default value is null, and you can't set a member on a null. You need to to test for null after the above statement, if it is null, instantiate manually. Also, a public field like that is a very bad idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM