How to tell if a variable is a reference or value data type
Today I've been learning about the ref, in, and out keywords. I understand that some variables are value types and some are reference types but I haven't really found and easy way of being able to tell which is which.
I understand that if I use the class keyword it will be a reference type and if I use struct it will be value. Is it really as simple as that? Its just I've noticed how everything including primitives like int are inheriting the object class so does that mean outside of things that have been explicitly marked as struct are reference?
A related question is around 15 years ago I learned a little bit of c++ and I learned that if anything is bigger than the size of a pointer it should be passed by reference to avoid the overhead of copying it.
As primitives like int in c# are slightly larger than a primitive in c++ being an object instance should we be using ref, in and out wherever possible? I can see the value of using in wherever possible because so far in my learning it feels like that is the closest we have to passing const.
Thank you very much for your time and help.
15 Replies
struct
s are value types, class
es are reference types, that's it
Generally speaking, in C#, you want to just use classes everywhere
Unless it's a tiny bit of corelated data, like some Vector3
struct or some such
C# is garbage collected, reference types being on the heap lend themselves better to the GCThank you, so if I use struct is it not garbage collected?
With some exceptions, but yeah
Okay cool thank you for your help. I think I'm starting to get the idea
Do you know if there is any disadvantage to liberal use of the in and out keywords though? Besides the obvious fact that they restrict the way that you use variables
I'm not aware of any disadvantages there
I'm not seeing them used all that often either, though
out
is pretty much exclusively used in the Try
pattern, like int.TryParse()
, etcyeah it might just be my old c++ brain, const was such a flexible keyword and we tended to use it everywhere, it felt like good practice back then but I'm aware that things have changed a lot in all that time
Things haven't really changed in the C++ land
C# is simply a different language
You wouldn't be using pointers in Python
Very true
I think in/out on references will essentially make the double refs, which will likely require two memory lookups to resolve any value. I think that 99.9%of the time, “in” is incorrect and unnecessary (unless you have a massive value type/struct and copying it is more expensive that the addition memory hit)
Okay it's just I've been writing code like this lately:
Class BankAccount{
Int balance
}
Class BankAccountReport{
Int balance
}
void displayBalance(BankAccountReport r){
}
To get around accidentally changing variables I shouldn't be changing. I'm probably over engineering there but I'm trying to get better at writing secure code
In could get rid of the report
Contrived example of course, quite often the report is a lot smaller than the object it's a report of but there is still duplication
generally in C#, unless you have a good reason to make something a struct just use a class
and the only numeric primitive larger than a pointer is
decimal
so getting cute with in/ref without actually benchmarking is just going to be extra work and harder to understand code
Also Int128/UInt128
Yeah okay fair enough. I was reading msdn last night and learned that if your variable is less than or equal to 3 words a ref is bigger anyway. Okay, looking at my code base there are only a few instances where im passing anything larger than a primitive. I think I'll do some benchmarking today and see how big the performance hit to using in and out is because if its free or negligible there are only a few areas where it would be even vaguely appropriate anyway.
i would only expect to see a meaningful difference with large structs but it's recommended to avoid those anyway