One of my rules of thumb is that as soon as you see some sort of UID
involved, you need a class. Here is my reasoning.
If something has a UID, then you typically want to refer to a single
copy of it, and make a duplicate only upon demand, because you
logically think of "that customer there" as opposed to "this customer
here". You may choose to clone it in order to create multiple versions
(the customer as it is in the database versus the changed customer to
be written to the database), but this is a conscious decision...
something that you do explicitly as part of your system design.
If you designed your system so that an item with a UID were copied
everywhere, I think that you (and other programmers coming after you)
would find the design difficult to follow: constantly having to
remember that there may be dozens or hundreds of copies of this
customer floating around in memory.
From the other side, things with value semantics usually have no unique
identifier. An "int" has no UID... it could serve as a UID for some
other type, but it itself does not have one. That's why copying it on
every call and every method return is not a problem: because there is
no need to distinguish between "this number 5" and "that number 5". The
value is all that matters.
The same goes for Point and Rectangle, by the way, two popular value
types in the .NET Framework: there is no concept of "this Point" versus
"that Point" if the two have the same coordinates.
So, in your case, I would definitely not make your customer a struct. I
would definitely make it a class, even if it were smaller than 16 bytes.