C
C#17h ago
Tempest

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
Angius
Angius17h ago
structs are value types, classes 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 GC
Tempest
TempestOP17h ago
Thank you, so if I use struct is it not garbage collected?
Angius
Angius17h ago
With some exceptions, but yeah
Tempest
TempestOP17h ago
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
Angius
Angius17h ago
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(), etc
Tempest
TempestOP17h ago
yeah 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
Angius
Angius17h ago
Things haven't really changed in the C++ land C# is simply a different language You wouldn't be using pointers in Python
Tempest
TempestOP16h ago
Very true
cned
cned15h ago
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)
Tempest
TempestOP15h ago
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
Jimmacle
Jimmacle14h ago
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
jcotton42
jcotton4213h ago
No description
asdf
asdf10h ago
Also Int128/UInt128
Tempest
TempestOP5h ago
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.
Jimmacle
Jimmacle4h ago
i would only expect to see a meaningful difference with large structs but it's recommended to avoid those anyway

Did you find this page helpful?