-1

I am using a public class Orders structure that is used to pass data to an API Post. The structure is defined as:

public class Orders{
  public string OrderID {get; set;}

  public class ShipTo {
      public string Address1 {get;set;}
      public string Address2 {get;set;}
  } 
}

In my code I use: Orders orders = new Orders();

then I can access the class orderID as: orders.OrderId = 123;

Then for ShipTo I set:

 Orders.ShipTo shipping = new Orders.ShipTo();

and can add a address using

 shipping.address1 = "my first street";

Great. Now I want to pass the entire Orders Class to a function that will read the both OrderId and Shipping address. I'm not sure how to pass one reference that allows me to read everything. Something that I thought would be logic is:

  thisOrder = orders.OrderId;
  thisShipAddress = orders.shipping.address1;

This isn't working. Your insight is appreciated.

IrvineCAGuy
  • 211
  • 2
  • 12
  • What do you mean by "not working"? Does it not compile (if so, what's the error code and message)? Does it throw an exception (if so, type and message)? Or, is `orders.shipping.address1` null or empty? – Flydog57 Apr 09 '21 at 22:27
  • 1
    For that you have to create a property with desired class in parent class. For example `public class Orders{ public string OrderID {get; set;} public ShitTo Shipping{get;set;} public class ShipTo { public string Address1 {get;set;} public string Address2 {get;set;} } }` Then you can access the needed property – Jay Nyxed Apr 09 '21 at 22:28
  • 1
    I suggest making `Orders` singular, `Order`. One instance represents a single order, not a collection of orders as the current name implies. –  Apr 09 '21 at 22:39

2 Answers2

2

You're confusing classes and instances. I would recommend you completely avoid nesting one class inside another class; it's an active hindrance to your learning and you will probably never in your coding life need to use a nested class

Change your code thus:

//in file Order.cs
public class Order{
  public string OrderID {get; set;}

  public Address ShipTo {get; set;}
  public Address BillTo {get; set;}
}

//in file Address.cs
public class Address {
  public string Address1 {get;set;}
  public string Address2 {get;set;}
}

Here I'm drawing a clear distinction between what something is (a class, like Address) and what it means (the name of the property, like the address you ShipTo versus the address you BillTo)

ShipTo and BillTo are both Addresses, and they may be same place or different, but they have different purposes. The name of the property reflects the purpose of the data, whereas the name of the class represents the structure of the data/what real world object or notion is modelled

Now you set them up like:

Order o = new Order();
o.OrderId = 1234;

o.ShipTo = new Address();
o.ShipTo.Address1 = "One Microsoft Way";
o.ShipTo.Address2 = "Redmond";

//this uses an initializer to set properties; same thing
o.BillTo = new Address () {
  Address1 = "One Infinite Loop",
  Address2 = "Cupertino"
}

You can use code like the first way to access your properties later:

public void SomeMethod(Order x){
  x.BillTo.Address2 = "Cuppateanow";
  Console.WriteLine(o.BillTo.Address1);
}

(Initializers help neaten up creating objects but there isn't a syntax like it for accessing data later, only for creating)

Remember, just because you make an Order with:

Order o = new Order();

Doesn't mean that o.BillTo is set to anything. C# does not create everything hierarchically for you. If you create an order but do not create a BillTo address and you then try to access the BillTo address you will get a NullReferenceException. You must make sure you have done a o.BillTo = new Address() before you try to o.BillTo.Address1 = ""


Side note; agree with Amy's point. Avoid ever pluralizing the name of a class. If a class is a collection of things you should end its name with "Collection" unless its name makes it obvious that it is a collection (like List, Hashset)

Properties that are a single entity should have a singular name public string OrderId ...

Properties that are a collection should have a plural name

public List<Address> Addresses ...

In this latter case your class might have an enum telling what type of address it is, and then an order can have any number of any types of address and this be very flexible- perhaps you will write logic that only allows one shipping and billing but you will send order updates out to every correspondence address associated with the order:

enum AddressType{
    Shipping,
    Billing,
    Correspondence
}

class Address{
    ...
    public AddressType AddressType ...
}

(Or we could subclass address.. but I'll leave that discussion for another tine)

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • Thank you for this. This should become a tutorial on class usage. The class I'm using is from an API they provided. I can create objects for each class. What I was hoping to be be lazy about is after all the values are set in each object, pass the entire enchilada to a a function call with on simple reference. – IrvineCAGuy Apr 10 '21 at 17:37
  • I did indeed do that with `public void SomeMethod(Order x)` but I can edit it to `public void SomeMethod(Order enchilordera)` if you like – Caius Jard Apr 10 '21 at 19:16
1

"the entire Orders Class" I guess you misunderstand what nested classes are. They don't belong to the parent class, the instances of the outer and the instances of the inner are not related at all. Nested classes are just in the namespace of the outer class.

Maybe you want a property ShipTo in the Orders-class(singular would be better).

public class Orders
{
    public string OrderID { get; set; }
    public ShipTo ShipAddresses {get; set; }

    public class ShipTo
    {
        public string Address1 { get; set; }
        public string Address2 { get; set; }
    }
}

Now it works:

public void DoSomething(Orders order)
{
    thisOrder = order.OrderID;
    thisShipAddress = order.ShipAddresses.Address1;
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 1
    Good answer, but you should put `ShipTo` outside of the scope of the class so he understands that its not necessary to nest it. – John Apr 09 '21 at 22:44
  • Getting closer to understanding this. I used this structure to simplify the question. Intellisense does 'see' the elements in the structure. Trying to Set the value of Address1 using order.ShippingAddresses.Address1="my address" returns an runtime error System.NullReferenceException: 'Object reference not set to an instance of an object.' Orders.shipAddresses.get returned null. I am trying to 'set' the value, not get it. Using Try/Catch the error is "Object reference not set to an instance of an object." – IrvineCAGuy Apr 10 '21 at 02:03
  • @IrvineCAGuy https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it –  Apr 10 '21 at 06:13