Yes, you can do it, but you need to bear a couple of things in mind.
First is that a value type (struct) is stored on the stack (often, not always, see comment-thread), rather than the heap. The stack is limited in size and large objects shouldn't be stored on it. That said, there is a minor performance benefit to storing variables on the stack.
The next is that a value type passed as a method argument will be copied, rather than referenced. This can be a good thing. At least you know that your variable isn't going to be changed by the method. However, the copy is stored on the stack, so be careful. Also, sometimes you want a method to be able to edit the contents of your object.
Finally, you need to know that reference objects within a struct are just pointers to objects on the heap. So if you edit the contents of one of those classes (unless, like a string, they are coded to be immutable), you are going to affect the contents of your own object, even though it is supposedly immutable. This can be very confusing.
As soon as you said that some of the contents are reference objects, I thought "I'd just stick to a class."
As a general rule:
- Only use structs to hold other immutable objects.
- Only use structs for small collections of data.
- Only use structs where changing one item within it will probably change all of the others.
Take an address as a good example:
- All contents are strings and thus immutable.
- It's only a half-dozen pointers.
- While you might remain in the same zipcode, for example, if you move house then you probably change your entire address.